blob: a744ae031592ed2464c3c6d6a1acc06fef6e351c [file] [log] [blame]
Maxwell Hendersonf63a0d92023-06-24 14:49:51 -07001#include "ctre/phoenix/cci/Diagnostics_CCI.h"
2#include "ctre/phoenix6/TalonFX.hpp"
3
4#include "aos/events/shm_event_loop.h"
5#include "aos/init.h"
6#include "frc971/control_loops/control_loops_generated.h"
7#include "frc971/wpilib/can_sensor_reader.h"
8#include "frc971/wpilib/falcon.h"
9#include "frc971/wpilib/sensor_reader.h"
10#include "frc971/wpilib/swerve/swerve_drivetrain_writer.h"
11#include "frc971/wpilib/wpilib_robot_base.h"
12#include "y2023_bot4/constants.h"
13#include "y2023_bot4/drivetrain_can_position_generated.h"
14#include "y2023_bot4/drivetrain_position_generated.h"
15
16DEFINE_bool(ctre_diag_server, false,
17 "If true, enable the diagnostics server for interacting with "
18 "devices on the CAN bus using Phoenix Tuner");
19
20using frc971::wpilib::CANSensorReader;
21using frc971::wpilib::Falcon;
22using frc971::wpilib::swerve::DrivetrainWriter;
23using frc971::wpilib::swerve::SwerveModule;
24
25namespace drivetrain = frc971::control_loops::drivetrain;
26
27namespace y2023_bot4 {
28namespace wpilib {
29namespace {
30
31template <class T>
32T value_or_exit(std::optional<T> optional) {
33 CHECK(optional.has_value());
34 return optional.value();
35}
36
37flatbuffers::Offset<frc971::AbsolutePosition> module_offset(
38 frc971::AbsolutePosition::Builder builder,
39 frc971::wpilib::AbsoluteEncoder *module) {
40 builder.add_encoder(module->ReadRelativeEncoder());
41 builder.add_absolute_encoder(module->ReadAbsoluteEncoder());
42
43 return builder.Finish();
44}
45
46flatbuffers::Offset<SwerveModuleCANPosition> can_module_offset(
47 SwerveModuleCANPosition::Builder builder,
48 std::shared_ptr<SwerveModule> module) {
49 std::optional<flatbuffers::Offset<control_loops::CANFalcon>> rotation_offset =
50 module->rotation->TakeOffset();
51 std::optional<flatbuffers::Offset<control_loops::CANFalcon>>
52 translation_offset = module->translation->TakeOffset();
53
54 CHECK(rotation_offset.has_value());
55 CHECK(translation_offset.has_value());
56
57 builder.add_rotation(rotation_offset.value());
58 builder.add_translation(translation_offset.value());
59
60 return builder.Finish();
61}
62
63constexpr double kMaxFastEncoderPulsesPerSecond = std::max({
64 constants::Values::kMaxDrivetrainEncoderPulsesPerSecond(),
65});
66static_assert(kMaxFastEncoderPulsesPerSecond <= 1300000,
67 "fast encoders are too fast");
68} // namespace
69
70class SensorReader : public ::frc971::wpilib::SensorReader {
71 public:
72 SensorReader(aos::ShmEventLoop *event_loop,
73 std::shared_ptr<const constants::Values> values)
74 : ::frc971::wpilib::SensorReader(event_loop),
75 values_(values),
76 drivetrain_position_sender_(
77 event_loop->MakeSender<AbsoluteDrivetrainPosition>("/drivetrain")) {
78 UpdateFastEncoderFilterHz(kMaxFastEncoderPulsesPerSecond);
79 event_loop->SetRuntimeAffinity(aos::MakeCpusetFromCpus({0}));
80 }
81
82 void RunIteration() override {
83 {
84 auto builder = drivetrain_position_sender_.MakeBuilder();
85
86 auto front_left_offset =
87 module_offset(builder.MakeBuilder<frc971::AbsolutePosition>(),
88 &front_left_encoder_);
89 auto front_right_offset =
90 module_offset(builder.MakeBuilder<frc971::AbsolutePosition>(),
91 &front_right_encoder_);
92 auto back_left_offset = module_offset(
93 builder.MakeBuilder<frc971::AbsolutePosition>(), &back_left_encoder_);
94 auto back_right_offset =
95 module_offset(builder.MakeBuilder<frc971::AbsolutePosition>(),
96 &back_right_encoder_);
97
98 AbsoluteDrivetrainPosition::Builder drivetrain_position_builder =
99 builder.MakeBuilder<AbsoluteDrivetrainPosition>();
100
101 drivetrain_position_builder.add_follower_wheel_one_position(
102 follower_wheel_one_encoder_->GetRaw());
103 drivetrain_position_builder.add_follower_wheel_two_position(
104 follower_wheel_two_encoder_->GetRaw());
105
106 drivetrain_position_builder.add_front_left_position(front_left_offset);
107 drivetrain_position_builder.add_front_right_position(front_right_offset);
108 drivetrain_position_builder.add_back_left_position(back_left_offset);
109 drivetrain_position_builder.add_back_right_position(back_right_offset);
110
111 builder.CheckOk(builder.Send(drivetrain_position_builder.Finish()));
112 }
113 }
114
115 void set_follower_wheel_one_encoder(std::unique_ptr<frc::Encoder> encoder) {
116 fast_encoder_filter_.Add(encoder.get());
117 follower_wheel_one_encoder_ = std::move(encoder);
118 follower_wheel_one_encoder_->SetMaxPeriod(0.005);
119 }
120 void set_follower_wheel_two_encoder(std::unique_ptr<frc::Encoder> encoder) {
121 fast_encoder_filter_.Add(encoder.get());
122 follower_wheel_two_encoder_ = std::move(encoder);
123 follower_wheel_two_encoder_->SetMaxPeriod(0.005);
124 }
125
126 void set_front_left_encoder(std::unique_ptr<frc::Encoder> encoder) {
127 fast_encoder_filter_.Add(encoder.get());
128 front_left_encoder_.set_encoder(std::move(encoder));
129 }
130 void set_front_left_absolute_pwm(
131 std::unique_ptr<frc::DigitalInput> absolute_pwm) {
132 front_left_encoder_.set_absolute_pwm(std::move(absolute_pwm));
133 }
134
135 void set_front_right_encoder(std::unique_ptr<frc::Encoder> encoder) {
136 fast_encoder_filter_.Add(encoder.get());
137 front_right_encoder_.set_encoder(std::move(encoder));
138 }
139 void set_front_right_absolute_pwm(
140 std::unique_ptr<frc::DigitalInput> absolute_pwm) {
141 front_right_encoder_.set_absolute_pwm(std::move(absolute_pwm));
142 }
143
144 void set_back_left_encoder(std::unique_ptr<frc::Encoder> encoder) {
145 fast_encoder_filter_.Add(encoder.get());
146 back_left_encoder_.set_encoder(std::move(encoder));
147 }
148 void set_back_left_absolute_pwm(
149 std::unique_ptr<frc::DigitalInput> absolute_pwm) {
150 back_left_encoder_.set_absolute_pwm(std::move(absolute_pwm));
151 }
152
153 void set_back_right_encoder(std::unique_ptr<frc::Encoder> encoder) {
154 fast_encoder_filter_.Add(encoder.get());
155 back_right_encoder_.set_encoder(std::move(encoder));
156 }
157 void set_back_right_absolute_pwm(
158 std::unique_ptr<frc::DigitalInput> absolute_pwm) {
159 back_right_encoder_.set_absolute_pwm(std::move(absolute_pwm));
160 }
161
162 private:
163 std::shared_ptr<const constants::Values> values_;
164
165 aos::Sender<AbsoluteDrivetrainPosition> drivetrain_position_sender_;
166
167 std::unique_ptr<frc::Encoder> follower_wheel_one_encoder_,
168 follower_wheel_two_encoder_;
169
170 frc971::wpilib::AbsoluteEncoder front_left_encoder_, front_right_encoder_,
171 back_left_encoder_, back_right_encoder_;
172};
173
174class WPILibRobot : public ::frc971::wpilib::WPILibRobotBase {
175 public:
176 ::std::unique_ptr<frc::Encoder> make_encoder(int index) {
177 return std::make_unique<frc::Encoder>(10 + index * 2, 11 + index * 2, false,
178 frc::Encoder::k4X);
179 }
180 void Run() override {
181 std::shared_ptr<const constants::Values> values =
182 std::make_shared<const constants::Values>(constants::MakeValues());
183
184 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
185 aos::configuration::ReadConfig("aos_config.json");
186
187 std::vector<ctre::phoenix6::BaseStatusSignal *> signals_registry;
188 std::vector<std::shared_ptr<Falcon>> falcons;
189
190 // TODO(max): Change the CanBus names with TalonFX software.
191 std::shared_ptr<SwerveModule> front_left = std::make_shared<SwerveModule>(
192 frc971::wpilib::FalconParams{6, false},
193 frc971::wpilib::FalconParams{5, false}, "Drivetrain Bus",
194 &signals_registry, constants::Values::kDrivetrainStatorCurrentLimit(),
195 constants::Values::kDrivetrainSupplyCurrentLimit());
196 std::shared_ptr<SwerveModule> front_right = std::make_shared<SwerveModule>(
197 frc971::wpilib::FalconParams{3, false},
198 frc971::wpilib::FalconParams{4, false}, "Drivetrain Bus",
199 &signals_registry, constants::Values::kDrivetrainStatorCurrentLimit(),
200 constants::Values::kDrivetrainSupplyCurrentLimit());
201 std::shared_ptr<SwerveModule> back_left = std::make_shared<SwerveModule>(
202 frc971::wpilib::FalconParams{8, false},
203 frc971::wpilib::FalconParams{7, false}, "Drivetrain Bus",
204 &signals_registry, constants::Values::kDrivetrainStatorCurrentLimit(),
205 constants::Values::kDrivetrainSupplyCurrentLimit());
206 std::shared_ptr<SwerveModule> back_right = std::make_shared<SwerveModule>(
207 frc971::wpilib::FalconParams{2, false},
208 frc971::wpilib::FalconParams{1, false}, "Drivetrain Bus",
209 &signals_registry, constants::Values::kDrivetrainStatorCurrentLimit(),
210 constants::Values::kDrivetrainSupplyCurrentLimit());
211
212 // Thread 1
213 aos::ShmEventLoop can_sensor_reader_event_loop(&config.message());
214 can_sensor_reader_event_loop.set_name("CANSensorReader");
215
216 falcons.push_back(front_left->rotation);
217 falcons.push_back(front_left->translation);
218
219 falcons.push_back(front_right->rotation);
220 falcons.push_back(front_right->translation);
221
222 falcons.push_back(back_left->rotation);
223 falcons.push_back(back_left->translation);
224
225 falcons.push_back(back_right->rotation);
226 falcons.push_back(back_right->translation);
227
228 aos::Sender<AbsoluteCANPosition> can_position_sender =
229 can_sensor_reader_event_loop.MakeSender<AbsoluteCANPosition>(
230 "/drivetrain");
231
232 CANSensorReader can_sensor_reader(
233 &can_sensor_reader_event_loop, std::move(signals_registry), falcons,
234 [this, falcons, front_left, front_right, back_left, back_right,
235 &can_position_sender](ctre::phoenix::StatusCode status) {
236 // TODO(max): use status properly in the flatbuffer.
237 (void)status;
238
239 auto builder = can_position_sender.MakeBuilder();
240
241 for (auto falcon : falcons) {
242 falcon->RefreshNontimesyncedSignals();
243 falcon->SerializePosition(builder.fbb(), 1.0);
244 }
245
246 auto front_left_offset = can_module_offset(
247 builder.MakeBuilder<SwerveModuleCANPosition>(), front_left);
248 auto front_right_offset = can_module_offset(
249 builder.MakeBuilder<SwerveModuleCANPosition>(), front_right);
250 auto back_left_offset = can_module_offset(
251 builder.MakeBuilder<SwerveModuleCANPosition>(), back_left);
252 auto back_right_offset = can_module_offset(
253 builder.MakeBuilder<SwerveModuleCANPosition>(), back_right);
254
255 AbsoluteCANPosition::Builder can_position_builder =
256 builder.MakeBuilder<AbsoluteCANPosition>();
257
258 can_position_builder.add_front_left(front_left_offset);
259 can_position_builder.add_front_right(front_right_offset);
260 can_position_builder.add_back_left(back_left_offset);
261 can_position_builder.add_back_right(back_right_offset);
262
263 builder.CheckOk(builder.Send(can_position_builder.Finish()));
264 });
265
266 AddLoop(&can_sensor_reader_event_loop);
267
268 // Thread 2
269 // Setup CAN
270 if (!FLAGS_ctre_diag_server) {
271 c_Phoenix_Diagnostics_SetSecondsToStart(-1);
272 c_Phoenix_Diagnostics_Dispose();
273 }
274
275 ctre::phoenix::platform::can::CANComm_SetRxSchedPriority(
276 constants::Values::kDrivetrainRxPriority, true, "Drivetrain Bus");
277 ctre::phoenix::platform::can::CANComm_SetTxSchedPriority(
278 constants::Values::kDrivetrainTxPriority, true, "Drivetrain Bus");
279
280 aos::ShmEventLoop drivetrain_writer_event_loop(&config.message());
281 drivetrain_writer_event_loop.set_name("DrivetrainWriter");
282
283 DrivetrainWriter drivetrain_writer(
284 &drivetrain_writer_event_loop,
285 constants::Values::kDrivetrainWriterPriority, 12);
286
287 drivetrain_writer.set_falcons(front_left, front_right, back_left,
288 back_right);
289
290 AddLoop(&drivetrain_writer_event_loop);
291
292 // Thread 3
293 aos::ShmEventLoop sensor_reader_event_loop(&config.message());
294 sensor_reader_event_loop.set_name("SensorReader");
295 SensorReader sensor_reader(&sensor_reader_event_loop, values);
296
297 sensor_reader.set_follower_wheel_one_encoder(make_encoder(4));
298 sensor_reader.set_follower_wheel_two_encoder(make_encoder(5));
299
300 sensor_reader.set_front_left_encoder(make_encoder(1));
301 sensor_reader.set_front_left_absolute_pwm(
302 std::make_unique<frc::DigitalInput>(1));
303
304 sensor_reader.set_front_right_encoder(make_encoder(0));
305 sensor_reader.set_front_right_absolute_pwm(
306 std::make_unique<frc::DigitalInput>(0));
307
308 sensor_reader.set_back_left_encoder(make_encoder(2));
309 sensor_reader.set_back_left_absolute_pwm(
310 std::make_unique<frc::DigitalInput>(2));
311
312 sensor_reader.set_back_right_encoder(make_encoder(3));
313 sensor_reader.set_back_right_absolute_pwm(
314 std::make_unique<frc::DigitalInput>(3));
315
316 AddLoop(&sensor_reader_event_loop);
317
318 RunLoops();
319 }
320};
321
322} // namespace wpilib
323} // namespace y2023_bot4
324
325AOS_ROBOT_CLASS(::y2023_bot4::wpilib::WPILibRobot)