2025-Robot
Robot code for 2025 FRC season by Argos, FRC team #1756
Loading...
Searching...
No Matches
swerve_drive_subsystem.h
Go to the documentation of this file.
1
4
5#pragma once
6
7#include <choreo/trajectory/SwerveSample.h>
8#include <frc/Timer.h>
9#include <frc/controller/HolonomicDriveController.h>
10#include <frc/controller/PIDController.h>
11#include <frc/controller/ProfiledPIDController.h>
12#include <frc/geometry/Pose2d.h>
13#include <frc/geometry/Rotation2d.h>
14#include <frc/kinematics/ChassisSpeeds.h>
15#include <frc/kinematics/SwerveDriveKinematics.h>
16#include <frc/kinematics/SwerveDriveOdometry.h>
17#include <frc/kinematics/SwerveModulePosition.h>
18#include <frc/kinematics/SwerveModuleState.h>
19#include <frc/smartdashboard/Field2d.h>
20#include <frc2/command/SubsystemBase.h>
21#include <wpi/DataLog.h>
22
23#include <array>
24#include <memory>
25#include <mutex>
26#include <thread>
27
28#include <ctre/phoenix6/CANcoder.hpp>
29#include <ctre/phoenix6/Pigeon2.hpp>
30#include <ctre/phoenix6/TalonFX.hpp>
31
37#include "ctre/phoenix6/sim/CANcoderSimState.hpp"
38#include "ctre/phoenix6/sim/TalonFXSimState.hpp"
39#include "frc/StateSpaceUtil.h"
40#include "frc/estimator/SwerveDrivePoseEstimator.h"
41#include "frc/geometry/Transform3d.h"
42
44 public:
45 // MOTORS
46 ctre::phoenix6::hardware::TalonFX m_drive;
47 ctre::phoenix6::hardware::TalonFX m_turn;
48 // ENCODER
49 ctre::phoenix6::hardware::CANcoder m_encoder;
50
58 SwerveModule(const argos_lib::CANAddress& driveAddr,
59 const argos_lib::CANAddress& turnAddr,
60 const argos_lib::CANAddress& encoderAddr);
61
62 frc::SwerveModuleState GetState();
63 frc::SwerveModulePosition GetPosition();
64 void SimulationPeriodic(const frc::SwerveModuleState& desiredState, units::second_t dt);
65
66 private:
67 // Internal state to track simulated drive position (in sensor units).
68 units::turn_t m_simDrivePos = 0.0_tr;
69};
70
75class SwerveDriveSubsystem : public frc2::SubsystemBase {
76 public:
82
83 explicit SwerveDriveSubsystem(const argos_lib::RobotInstance instance);
84
85 virtual ~SwerveDriveSubsystem();
86
87 void SimulationPeriodic() override;
88
92 void Disable();
93
101 void SwerveDrive(const double fwVelocity, const double sideVelocity, const double rotVelocity);
102
107 void SwerveDrive(const units::degree_t& velAngle, const double& velocity, const double& rotVelocity);
108
112 void SwerveDrive(const units::degree_t& velAngle, const double& velocity);
113
116 void SwerveDrive(frc::ChassisSpeeds desiredChassisSpeed);
117
120 void SwerveDrive(const choreo::SwerveSample& sample);
121
125 void StopDrive();
126
128 // choreolib::ChoreoControllerFunction GetChoreoControllerFunction();
129
136 void Home(const units::degree_t& angle);
137
144 void FieldHome(units::degree_t homeAngle = 0_deg, bool updateOdometry = true);
145
146 void FlipFieldHome();
147
153 void InitializeOdometry(const frc::Pose2d& currentPose);
154
155 frc::Rotation2d GetContinuousOdometryAngle();
156
157 frc::Rotation2d GetRawOdometryAngle();
158
159 frc::Rotation2d GetNearestSquareAngle();
160
161 frc::Pose2d GetContinuousOdometry();
162
163 frc::Pose2d GetRawOdometry();
164
168 void UpdateEstimatedPose();
169
176 units::degree_t GetFieldCentricAngle();
177
183 frc::Pose2d GetPoseEstimate(const frc::Pose2d& robotPose, const units::millisecond_t& latency);
184
185 void UpdateVisionMeasurement(const frc::Pose2d& poseEstimate,
186 units::second_t timestamp,
187 const wpi::array<double, 3>& visionMeasurementStdDevs);
188
190
195 void InitializeMotors();
196
205 void UpdateFollowerLinearPIDParams(double kP, double kI, double kD);
206
215 void UpdateFollowerRotationalPIDParams(double kP, double kI, double kD);
216
221
227 bool ProfileIsComplete() const;
228
234 bool IsFollowingProfile() const;
235
242 frc::ChassisSpeeds GetChassisVelocity();
243
247 void LockWheels();
248
249 bool GetManualOverride();
250
256 units::degree_t GetRobotPitch() { return m_pigeonIMU.GetRoll().GetValue(); }
257
263 units::degrees_per_second_t GetRobotPitchRate();
264
265 units::degree_t GetIMUYaw();
266 units::degrees_per_second_t GetIMUYawRate();
267
268 void SimDrive();
269
270 void SetTrajectoryDisplay(const std::vector<frc::Pose2d>& trajectory);
271
272 private:
274
276
281
282 // GYROSCOPIC SENSORS
283 ctre::phoenix6::hardware::Pigeon2 m_pigeonIMU;
284
285 units::degree_t m_fieldHomeOffset;
286
291 struct Velocities {
292 const double fwVelocity;
293 const double sideVelocity;
294 const double rotVelocity;
295 };
296
297 frc::SwerveDriveKinematics<4> m_swerveDriveKinematics;
298
299 frc::SwerveDriveOdometry<4> m_odometry;
300 units::degree_t m_prevOdometryAngle;
302
303 frc::SwerveDrivePoseEstimator<4> m_poseEstimator;
305 std::thread m_odometryThread;
306 std::chrono::time_point<std::chrono::steady_clock>
309
310 // std::FILE SYSTEM HOMING STORAGE
312
316 std::chrono::time_point<std::chrono::steady_clock> m_swerveProfileStartTime;
317 frc::PIDController m_xPID;
318 frc::PIDController m_yPID;
319 frc::PIDController m_thetaPID;
320
321 std::unique_ptr<argos_lib::NTMotorPIDTuner> m_driveMotorPIDTuner;
322 std::unique_ptr<argos_lib::NTSubscriber> m_linearFollowerTuner_P;
323 std::unique_ptr<argos_lib::NTSubscriber> m_linearFollowerTuner_I;
324 std::unique_ptr<argos_lib::NTSubscriber> m_linearFollowerTuner_D;
325 std::unique_ptr<argos_lib::NTSubscriber> m_rotationalFollowerTuner_P;
326 std::unique_ptr<argos_lib::NTSubscriber> m_rotationalFollowerTuner_I;
327 std::unique_ptr<argos_lib::NTSubscriber> m_rotationalFollowerTuner_D;
328
329 wpi::array<frc::SwerveModuleState, 4> GetRawModuleStates(frc::ChassisSpeeds velocities);
336 wpi::array<frc::SwerveModuleState, 4> GetRawModuleStates(SwerveDriveSubsystem::Velocities velocities);
337
343 wpi::array<frc::SwerveModuleState, 4> GetCurrentModuleStates();
344
350 wpi::array<frc::SwerveModulePosition, 4> GetCurrentModulePositions();
351
358 void HomeToFS(const units::degree_t& angle);
359
365
366 void ResetIMUYaw();
367
368 wpi::array<frc::SwerveModuleState, 4> OptimizeAllModules(wpi::array<frc::SwerveModuleState, 4> rawStates);
369
370 void ClosedLoopDrive(wpi::array<frc::SwerveModuleState, 4> moduleStates);
371
372 wpi::log::StructLogEntry<frc::Pose2d> m_poseEstimateLogger;
373 wpi::log::StructArrayLogEntry<frc::SwerveModuleState> m_setpointLogger;
374 wpi::log::StructArrayLogEntry<frc::SwerveModuleState> m_stateLogger;
375
380 };
382
384
385 // Field2D for visualization
386 frc::Field2d m_field;
387};
Subsystem for controlling the swerve drivetrain of the robot.
Definition swerve_drive_subsystem.h:75
void Home(const units::degree_t &angle)
Save homes to persistent storage and updates module motors.
Definition swerve_drive_subsystem.cpp:524
frc::Pose2d GetContinuousOdometry()
Definition swerve_drive_subsystem.cpp:650
double m_simulatedHeading
Definition swerve_drive_subsystem.h:383
void Disable()
Handle the robot disabling.
Definition swerve_drive_subsystem.cpp:244
void UpdateVisionMeasurement(const frc::Pose2d &poseEstimate, units::second_t timestamp, const wpi::array< double, 3 > &visionMeasurementStdDevs)
Definition swerve_drive_subsystem.cpp:821
void HomeToFS(const units::degree_t &angle)
Save homes to a file.
Definition swerve_drive_subsystem.cpp:840
void FieldHome(units::degree_t homeAngle=0_deg, bool updateOdometry=true)
Tell the robot it's in it's correct field-oriented "Front".
Definition swerve_drive_subsystem.cpp:575
void UpdateFollowerRotationalPIDParams(double kP, double kI, double kD)
Change PID parameters for rotational follower. These adjust velocities based on angle error from path...
Definition swerve_drive_subsystem.cpp:931
SwerveModule m_backRight
Back right swerve module.
Definition swerve_drive_subsystem.h:279
frc::PIDController m_xPID
Correction parameters for x error when following drive profile.
Definition swerve_drive_subsystem.h:317
SwerveModule m_frontLeft
Front left swerve module.
Definition swerve_drive_subsystem.h:277
wpi::log::StructArrayLogEntry< frc::SwerveModuleState > m_setpointLogger
Definition swerve_drive_subsystem.h:373
wpi::array< frc::SwerveModuleState, 4 > OptimizeAllModules(wpi::array< frc::SwerveModuleState, 4 > rawStates)
Definition swerve_drive_subsystem.cpp:965
std::chrono::time_point< std::chrono::steady_clock > m_swerveProfileStartTime
Time when active profile began.
Definition swerve_drive_subsystem.h:316
units::degrees_per_second_t GetIMUYawRate()
Definition swerve_drive_subsystem.cpp:953
virtual ~SwerveDriveSubsystem()
Definition swerve_drive_subsystem.cpp:239
std::unique_ptr< argos_lib::NTSubscriber > m_linearFollowerTuner_D
Definition swerve_drive_subsystem.h:324
std::unique_ptr< argos_lib::NTSubscriber > m_rotationalFollowerTuner_D
Definition swerve_drive_subsystem.h:327
DriveControlMode
Enumerator for either field-centric or robot centric drive modes.
Definition swerve_drive_subsystem.h:81
@ robotCentricControl
Definition swerve_drive_subsystem.h:81
@ fieldCentricControl
Definition swerve_drive_subsystem.h:81
bool m_profileComplete
True once a drive profile has been completed.
Definition swerve_drive_subsystem.h:314
void CancelDrivingProfile()
Cancel the current driving profile without marking it complete.
Definition swerve_drive_subsystem.cpp:936
bool m_followingProfile
True when an incomplete drive profile is being run.
Definition swerve_drive_subsystem.h:313
bool IsFollowingProfile() const
Check if drivetrain is following a profile.
Definition swerve_drive_subsystem.cpp:945
units::degree_t m_fieldHomeOffset
Offset from IMU angle to 0 field angle (intake away from driver station)
Definition swerve_drive_subsystem.h:285
void UpdateFollowerLinearPIDParams(double kP, double kI, double kD)
Change PID parameters for linear follower. These adjust velocities based on distance error from path ...
Definition swerve_drive_subsystem.cpp:924
frc::PIDController m_thetaPID
Correction parameters for y error when following drive profile.
Definition swerve_drive_subsystem.h:319
frc::Pose2d GetRawOdometry()
Definition swerve_drive_subsystem.cpp:666
void InitializeOdometry(const frc::Pose2d &currentPose)
Set current robot position. Useful for initializing initial position before autonomous.
Definition swerve_drive_subsystem.cpp:592
void InitializeMotorsFromFS()
Initialize motors from saved file.
Definition swerve_drive_subsystem.cpp:850
frc::Pose2d GetPoseEstimate(const frc::Pose2d &robotPose, const units::millisecond_t &latency)
Get the latest pose estimate.
Definition swerve_drive_subsystem.cpp:799
wpi::array< frc::SwerveModuleState, 4 > GetRawModuleStates(frc::ChassisSpeeds velocities)
Definition swerve_drive_subsystem.cpp:299
units::degree_t GetIMUYaw()
Definition swerve_drive_subsystem.cpp:949
frc::SwerveDriveKinematics< 4 > m_swerveDriveKinematics
Kinematics model for swerve drive system.
Definition swerve_drive_subsystem.h:297
units::degree_t GetRobotPitch()
Get the robot pitch as determined by the pigeon IMU.
Definition swerve_drive_subsystem.h:256
std::thread m_odometryThread
Updates robot odometry at very high rate.
Definition swerve_drive_subsystem.h:305
std::unique_ptr< argos_lib::NTMotorPIDTuner > m_driveMotorPIDTuner
Utility to tune drive motors.
Definition swerve_drive_subsystem.h:321
SwerveModule m_backLeft
Back left swerve module.
Definition swerve_drive_subsystem.h:280
DriveControlMode m_controlMode
Active control mode.
Definition swerve_drive_subsystem.h:275
void SimDrive()
Definition swerve_drive_subsystem.cpp:258
wpi::array< frc::SwerveModulePosition, 4 > GetCurrentModulePositions()
Get the active positions of all swerve modules.
Definition swerve_drive_subsystem.cpp:349
units::degree_t GetFieldCentricAngle()
Get the field-centric angle of the robot based on gyro and saved reference orientation.
Definition swerve_drive_subsystem.cpp:795
void SetControlMode(SwerveDriveSubsystem::DriveControlMode controlMode)
Definition swerve_drive_subsystem.cpp:832
void SimulationPeriodic() override
Definition swerve_drive_subsystem.cpp:250
frc::Field2d m_field
Definition swerve_drive_subsystem.h:386
wpi::array< frc::SwerveModuleState, 4 > GetCurrentModuleStates()
Get the active states of all swerve modules.
Definition swerve_drive_subsystem.cpp:345
std::unique_ptr< argos_lib::NTSubscriber > m_linearFollowerTuner_P
Definition swerve_drive_subsystem.h:322
SwerveDriveSubsystem(const argos_lib::RobotInstance instance)
Definition swerve_drive_subsystem.cpp:33
bool ProfileIsComplete() const
Check if a driving profile path has been completed.
Definition swerve_drive_subsystem.cpp:941
frc::Rotation2d GetRawOdometryAngle()
Definition swerve_drive_subsystem.cpp:640
void SwerveDrive(const double fwVelocity, const double sideVelocity, const double rotVelocity)
Main drive function for the robot.
Definition swerve_drive_subsystem.cpp:353
std::unique_ptr< argos_lib::NTSubscriber > m_rotationalFollowerTuner_I
Definition swerve_drive_subsystem.h:326
std::chrono::time_point< std::chrono::steady_clock > m_odometryResetTime
Time when odometry was last reset to known position.
Definition swerve_drive_subsystem.h:307
void SetTrajectoryDisplay(const std::vector< frc::Pose2d > &trajectory)
Definition swerve_drive_subsystem.cpp:285
wpi::log::StructArrayLogEntry< frc::SwerveModuleState > m_stateLogger
Definition swerve_drive_subsystem.h:374
void InitializeMotors()
Initialize motors from persistent storage.
Definition swerve_drive_subsystem.cpp:836
void UpdateEstimatedPose()
Reads module states & gyro and updates pose estimator.
Definition swerve_drive_subsystem.cpp:681
wpi::log::StructLogEntry< frc::Pose2d > m_poseEstimateLogger
Definition swerve_drive_subsystem.h:372
units::degrees_per_second_t GetRobotPitchRate()
Get the rate of robot pitch.
Definition swerve_drive_subsystem.cpp:537
frc::ChassisSpeeds GetChassisVelocity()
Get the robot velocity in chassis frame (x toward intake, y toward left) based on GetCurrentModuleSta...
Definition swerve_drive_subsystem.cpp:961
std::unique_ptr< argos_lib::NTSubscriber > m_rotationalFollowerTuner_P
Definition swerve_drive_subsystem.h:325
ctre::phoenix6::hardware::Pigeon2 m_pigeonIMU
Definition swerve_drive_subsystem.h:283
void LockWheels()
Put the robot wheels in an x shape where it locks the movement of it.
Definition swerve_drive_subsystem.cpp:541
void StopDrive()
Stop all motors.
Definition swerve_drive_subsystem.cpp:507
SwerveModule m_frontRight
Front right swerve module.
Definition swerve_drive_subsystem.h:278
std::unique_ptr< argos_lib::NTSubscriber > m_linearFollowerTuner_I
Definition swerve_drive_subsystem.h:323
frc::Rotation2d GetNearestSquareAngle()
Definition swerve_drive_subsystem.cpp:645
std::mutex m_poseEstimatorLock
Definition swerve_drive_subsystem.h:304
frc::SwerveDriveOdometry< 4 > m_odometry
Odometry to track robot.
Definition swerve_drive_subsystem.h:299
bool m_manualOverride
Definition swerve_drive_subsystem.h:315
frc::Rotation2d GetContinuousOdometryAngle()
Definition swerve_drive_subsystem.cpp:617
units::degree_t m_continuousOdometryOffset
Offset to convert [-180,180] odometry angle to continuous angle.
Definition swerve_drive_subsystem.h:301
void ResetIMUYaw()
Definition swerve_drive_subsystem.cpp:957
argos_lib::SwerveFSHomingStorage m_fsStorage
Roborio filesystem access for homes.
Definition swerve_drive_subsystem.h:311
bool GetManualOverride()
Definition swerve_drive_subsystem.cpp:571
void ClosedLoopDrive(wpi::array< frc::SwerveModuleState, 4 > moduleStates)
Definition swerve_drive_subsystem.cpp:994
frc::SwerveDrivePoseEstimator< 4 > m_poseEstimator
accounts vision-based measurements for odometry
Definition swerve_drive_subsystem.h:303
void FlipFieldHome()
Definition swerve_drive_subsystem.cpp:588
SimVelocities m_simVelocities
Definition swerve_drive_subsystem.h:381
units::degree_t m_prevOdometryAngle
Last odometry angle used for continuous calculations.
Definition swerve_drive_subsystem.h:300
frc::PIDController m_yPID
Correction parameters for y error when following drive profile.
Definition swerve_drive_subsystem.h:318
bool m_stillRunning
false indicates subsystem is being destroyed
Definition swerve_drive_subsystem.h:308
argos_lib::RobotInstance m_instance
Definition swerve_drive_subsystem.h:273
Definition swerve_drive_subsystem.h:43
frc::SwerveModuleState GetState()
Definition swerve_drive_subsystem.cpp:912
ctre::phoenix6::hardware::CANcoder m_encoder
Definition swerve_drive_subsystem.h:49
units::turn_t m_simDrivePos
Definition swerve_drive_subsystem.h:68
ctre::phoenix6::hardware::TalonFX m_turn
Definition swerve_drive_subsystem.h:47
ctre::phoenix6::hardware::TalonFX m_drive
Definition swerve_drive_subsystem.h:46
frc::SwerveModulePosition GetPosition()
Definition swerve_drive_subsystem.cpp:918
void SimulationPeriodic(const frc::SwerveModuleState &desiredState, units::second_t dt)
Definition swerve_drive_subsystem.cpp:886
SwerveModule(const argos_lib::CANAddress &driveAddr, const argos_lib::CANAddress &turnAddr, const argos_lib::CANAddress &encoderAddr)
Construct a new Swerve Module object.
Definition swerve_drive_subsystem.cpp:879
Definition fs_homing.h:17
RobotInstance
Differentiates between practice robot and competition robot.
Definition config_types.h:13
Definition swerve_drive_subsystem.h:376
double fwVelocity
Definition swerve_drive_subsystem.h:377
double rotVelocity
Definition swerve_drive_subsystem.h:379
double sideVelocity
Definition swerve_drive_subsystem.h:378
A struct for holding the 3 different input velocities, for organization.
Definition swerve_drive_subsystem.h:291
const double sideVelocity
Definition swerve_drive_subsystem.h:293
const double rotVelocity
Definition swerve_drive_subsystem.h:294
const double fwVelocity
Definition swerve_drive_subsystem.h:292
Definition config_types.h:25