FRC Paradigm Shift #1259
Documentation for the 2021 Robot
SwerveModule Class Reference

Public Member Functions

 SwerveModule (int driveMotorChannel, int turningMotorChannel, GetPulseWidthCallback pulseWidthCallback, CANifier::PWMChannel pwmChannel, bool driveEncoderReversed, double offSet, const string &name)
 
void Periodic ()
 
SwerveModuleState GetState ()
 
void SetDesiredState (SwerveModuleState &state)
 
void ResetEncoders ()
 Resets the drive motor encoders to 0. More...
 
void ResetRelativeToAbsolute ()
 Resync the relative NEO turn encoder to the absolute encoder. More...
 

Private Types

using radians_per_second_squared_t = compound_unit< radians, inverse< squared< second >>>
 

Private Member Functions

double CalcAbsoluteAngle ()
 Calculate the absolute angle, in radians, based on the pulse widths from m_pulseWidthCallback. More...
 
double MinTurnRads (double init, double final, bool &bOutputReverse)
 
meters_per_second_t CalcMetersPerSec ()
 
double CalcTicksPer100Ms (meters_per_second_t speed)
 

Private Attributes

double m_offset
 The offset, in pulse widths, for syncing the relative encoder to the absolute encoder. More...
 
string m_name
 String used to identify each pod, used for SmartDashboard prints. More...
 
TalonFX m_driveMotor
 Falon 500 that drives the pod. More...
 
PIDLoaderFalcon m_drivePIDLoader
 PID param loader for the TalonFX. More...
 
PIDLoaderNEO m_turnPIDLoader
 PID param loader for the CANSparkMax. More...
 
GetPulseWidthCallback m_pulseWidthCallback
 
CANifier::PWMChannel m_pwmChannel
 
Timer m_timer
 Timer used to sync absolute and relative encoders on robot turn on. More...
 
NEO that turns the pod, controls angle with relative encoder and PID
CANSparkMax m_turningMotor
 
CANEncoder m_turnRelativeEncoder
 
CANPIDController m_turnPIDController = m_turningMotor.GetPIDController()
 

Detailed Description

Definition at line 51 of file SwerveModule.h.

Member Typedef Documentation

using SwerveModule::radians_per_second_squared_t = compound_unit<radians, inverse<squared<second>>>
private

Definition at line 53 of file SwerveModule.h.

Constructor & Destructor Documentation

SwerveModule::SwerveModule ( int  driveMotorChannel,
int  turningMotorChannel,
GetPulseWidthCallback  pulseWidthCallback,
CANifier::PWMChannel  pwmChannel,
bool  driveEncoderReversed,
double  offSet,
const string &  name 
)

Definition at line 11 of file SwerveModule.cpp.

References ModuleConstants::kMotorCurrentLimit, ModuleConstants::kTurnMotorRevsPerWheelRev, PIDLoaderFalcon::Load(), PIDLoaderNEO::Load(), m_driveMotor, m_drivePIDLoader, m_timer, m_turningMotor, m_turnPIDController, m_turnPIDLoader, and m_turnRelativeEncoder.

18  : m_offset(offset)
19  , m_name(name)
20  , m_driveMotor(driveMotorChannel)
21  , m_turningMotor(turningMotorChannel, CANSparkMax::MotorType::kBrushless)
24  , m_pulseWidthCallback(pulseWidthCallback)
25  , m_pwmChannel(pwmChannel)
26 {
27  StatorCurrentLimitConfiguration statorLimit { true, kMotorCurrentLimit, kMotorCurrentLimit, 2 };
28  m_driveMotor.ConfigStatorCurrentLimit(statorLimit);
29  SupplyCurrentLimitConfiguration supplyLimit { true, kMotorCurrentLimit, kMotorCurrentLimit, 2 };
30  m_driveMotor.ConfigSupplyCurrentLimit(supplyLimit);
31  m_turningMotor.SetSmartCurrentLimit(kMotorCurrentLimit);
32 
33  // Set up GetVelocity() to return meters per sec instead of RPM
34  m_turnRelativeEncoder.SetPositionConversionFactor(2.0 * wpi::math::pi / kTurnMotorRevsPerWheelRev);
35 
36  m_driveMotor.SetInverted(driveMotorReversed ? TalonFXInvertType::CounterClockwise : TalonFXInvertType::Clockwise);
37  m_turningMotor.SetInverted(false);
38  m_driveMotor.ConfigSelectedFeedbackSensor(TalonFXFeedbackDevice::IntegratedSensor);
39  m_turnPIDController.SetFeedbackDevice(m_turnRelativeEncoder);
40 
41  m_turningMotor.SetIdleMode(CANSparkMax::IdleMode::kBrake);
42  m_driveMotor.SetNeutralMode(NeutralMode::Brake);
43 
46 
47  m_timer.Reset();
48  m_timer.Start();
49 }
constexpr bool kDriveAdjust
Definition: Constants.h:151
constexpr bool kTurnAdjust
Definition: Constants.h:141
constexpr double kTurnP
Definition: Constants.h:142
constexpr uint kMotorCurrentLimit
Definition: Constants.h:137
constexpr double kTurnIZ
Definition: Constants.h:146
PIDLoaderFalcon m_drivePIDLoader
PID param loader for the TalonFX.
Definition: SwerveModule.h:111
CANEncoder m_turnRelativeEncoder
Definition: SwerveModule.h:105
constexpr double kDriveP
Definition: Constants.h:152
Timer m_timer
Timer used to sync absolute and relative encoders on robot turn on.
Definition: SwerveModule.h:121
constexpr double kDriveI
Definition: Constants.h:153
string m_name
String used to identify each pod, used for SmartDashboard prints.
Definition: SwerveModule.h:98
GetPulseWidthCallback m_pulseWidthCallback
Definition: SwerveModule.h:117
CANifier::PWMChannel m_pwmChannel
Definition: SwerveModule.h:118
void Load(CANPIDController &turnPIDController)
constexpr double kDriveFF
Definition: Constants.h:155
PIDLoaderNEO m_turnPIDLoader
PID param loader for the CANSparkMax.
Definition: SwerveModule.h:113
CANSparkMax m_turningMotor
Definition: SwerveModule.h:104
CANPIDController m_turnPIDController
Definition: SwerveModule.h:107
void Load(TalonFX &driveMotor)
constexpr double kTurnI
Definition: Constants.h:143
double m_offset
The offset, in pulse widths, for syncing the relative encoder to the absolute encoder.
Definition: SwerveModule.h:96
constexpr double kTurnMotorRevsPerWheelRev
Definition: Constants.h:125
constexpr double kTurnIA
Definition: Constants.h:145
constexpr double kTurnD
Definition: Constants.h:144
constexpr double kDriveD
Definition: Constants.h:154
TalonFX m_driveMotor
Falon 500 that drives the pod.
Definition: SwerveModule.h:101

Member Function Documentation

void SwerveModule::Periodic ( )

Definition at line 51 of file SwerveModule.cpp.

References CalcAbsoluteAngle(), m_name, m_timer, m_turnRelativeEncoder, and ResetRelativeToAbsolute().

52 {
53  if (m_timer.Get() < 5)
55 
56  double absAngle = CalcAbsoluteAngle();
57  SmartDashboard::PutNumber("D_SM_Rel " + m_name, m_turnRelativeEncoder.GetPosition());
58  SmartDashboard::PutNumber("D_SM_Abs " + m_name, absAngle);
59  SmartDashboard::PutNumber("D_SM_AbsDiff " + m_name, m_turnRelativeEncoder.GetPosition() - absAngle);
60  // SmartDashboard::PutNumber("D_SM_MPS " + m_name, CalcMetersPerSec().to<double>());
61  // SmartDashboard::PutNumber("D_SM_IError " + m_name, m_turnPIDController.GetIAccum());
62  // SmartDashboard::PutNumber("D_SM_TP100MS " + m_name, m_driveMotor.GetSelectedSensorVelocity());
63 }
CANEncoder m_turnRelativeEncoder
Definition: SwerveModule.h:105
Timer m_timer
Timer used to sync absolute and relative encoders on robot turn on.
Definition: SwerveModule.h:121
string m_name
String used to identify each pod, used for SmartDashboard prints.
Definition: SwerveModule.h:98
void ResetRelativeToAbsolute()
Resync the relative NEO turn encoder to the absolute encoder.
double CalcAbsoluteAngle()
Calculate the absolute angle, in radians, based on the pulse widths from m_pulseWidthCallback.
SwerveModuleState SwerveModule::GetState ( )

Get the state for the swerve module pod

Returns
The state (vector with speed and angle) representig the current module state
Todo:
Currently GetState uses the absolute angle instead of the relative angle that we should be using

Why do we find the absolute angle here instead of the relative angle?

Definition at line 65 of file SwerveModule.cpp.

References CalcAbsoluteAngle(), and CalcMetersPerSec().

66 {
68  return { CalcMetersPerSec(), Rotation2d(radian_t(CalcAbsoluteAngle()))};
69 }
meters_per_second_t CalcMetersPerSec()
double CalcAbsoluteAngle()
Calculate the absolute angle, in radians, based on the pulse widths from m_pulseWidthCallback.
void SwerveModule::SetDesiredState ( SwerveModuleState &  state)

Set the desired state for the swerve module pod

Parameters
stateThe state (vector with speed and angle) representing the desired module state

Definition at line 71 of file SwerveModule.cpp.

References CalcTicksPer100Ms(), PIDLoaderFalcon::LoadFromNetworkTable(), PIDLoaderNEO::LoadFromNetworkTable(), m_driveMotor, m_drivePIDLoader, m_turnPIDController, m_turnPIDLoader, m_turnRelativeEncoder, and MinTurnRads().

72 {
73  // Retrieving PID values from SmartDashboard if enabled
76 
77  // Get relative encoder position
78  double currentPosition = m_turnRelativeEncoder.GetPosition();
79 
80  // Calculate new turn position given current and desired position
81  bool bOutputReverse = false;
82  double minTurnRads = MinTurnRads(currentPosition, state.angle.Radians().to<double>(), bOutputReverse);
83  double direction = 1.0; // Sent to TalonFX
84  if (bOutputReverse)
85  direction = -1.0;
86 
87  // Set position reference of turnPIDController
88  double newPosition = currentPosition + minTurnRads;
89 
90  if (state.speed != 0_mps) {
91  #ifdef DISABLE_DRIVE
92  m_driveMotor.Set(TalonFXControlMode::Velocity, 0.0);
93  #else
94  m_driveMotor.Set(TalonFXControlMode::Velocity, direction * CalcTicksPer100Ms(state.speed));
95  #endif
96  }
97  else
98  m_driveMotor.Set(TalonFXControlMode::PercentOutput, 0.0);
99 
100  // Set the angle unless module is coming to a full stop
101  if (state.speed.to<double>() != 0.0)
102  m_turnPIDController.SetReference(newPosition, ControlType::kPosition);
103 
104  // SmartDashboard::PutNumber("D_SM_SetpointMPS " + m_name, state.speed.to<double>());
105  // SmartDashboard::PutNumber("D_SM_Error " + m_name, newPosition - m_turnRelativeEncoder.GetPosition());
106 }
PIDLoaderFalcon m_drivePIDLoader
PID param loader for the TalonFX.
Definition: SwerveModule.h:111
CANEncoder m_turnRelativeEncoder
Definition: SwerveModule.h:105
double CalcTicksPer100Ms(meters_per_second_t speed)
void LoadFromNetworkTable(CANPIDController &turnPIDController)
void LoadFromNetworkTable(TalonFX &driveMotor)
double MinTurnRads(double init, double final, bool &bOutputReverse)
PIDLoaderNEO m_turnPIDLoader
PID param loader for the CANSparkMax.
Definition: SwerveModule.h:113
CANPIDController m_turnPIDController
Definition: SwerveModule.h:107
TalonFX m_driveMotor
Falon 500 that drives the pod.
Definition: SwerveModule.h:101
void SwerveModule::ResetEncoders ( )

Resets the drive motor encoders to 0.

Definition at line 108 of file SwerveModule.cpp.

References m_driveMotor.

109 {
110  m_driveMotor.SetSelectedSensorPosition(0.0);
111 }
TalonFX m_driveMotor
Falon 500 that drives the pod.
Definition: SwerveModule.h:101
void SwerveModule::ResetRelativeToAbsolute ( )

Resync the relative NEO turn encoder to the absolute encoder.

Definition at line 123 of file SwerveModule.cpp.

References CalcAbsoluteAngle(), and m_turnRelativeEncoder.

124 {
126 }
CANEncoder m_turnRelativeEncoder
Definition: SwerveModule.h:105
double CalcAbsoluteAngle()
Calculate the absolute angle, in radians, based on the pulse widths from m_pulseWidthCallback.
double SwerveModule::CalcAbsoluteAngle ( )
private

Calculate the absolute angle, in radians, based on the pulse widths from m_pulseWidthCallback.

Definition at line 113 of file SwerveModule.cpp.

References DriveConstants::kPulseWidthToRadians, m_offset, m_pulseWidthCallback, and m_pwmChannel.

114 {
115  double pulseWidth = m_pulseWidthCallback(m_pwmChannel);
116  // Pulse Width per rotation is not equal for all encoders. Some are 0 - 3865, some are 0 - 4096
117  return fmod((pulseWidth - m_offset) * DriveConstants::kPulseWidthToRadians + 2.0 * wpi::math::pi, 2.0 * wpi::math::pi);
118  // SmartDashboard::PutNumber("D_SM_PW " + m_name, pulseWidth);
119  // SmartDashboard::PutNumber("D_SM_AA " + m_name, absAngle);
120  // Convert CW to CCW? absAngle = 2.0 * wpi::math::pi - absAngle;
121 }
GetPulseWidthCallback m_pulseWidthCallback
Definition: SwerveModule.h:117
CANifier::PWMChannel m_pwmChannel
Definition: SwerveModule.h:118
constexpr double kPulseWidthToRadians
Definition: Constants.h:99
double m_offset
The offset, in pulse widths, for syncing the relative encoder to the absolute encoder.
Definition: SwerveModule.h:96
double SwerveModule::MinTurnRads ( double  init,
double  final,
bool &  bOutputReverse 
)
private

Determine the smallest magnitude delta angle that can be added to initial angle that will result in an angle equivalent (but not necessarily equal) to final angle. All angles in radians Currently final - init difference is always chosen regardless of angle

Definition at line 133 of file SwerveModule.cpp.

References Util::NegPiToPiRads(), and Util::ZeroTo2PiRads().

134 {
135  init = Util::ZeroTo2PiRads(init);
136  final = Util::ZeroTo2PiRads(final);
137 
138  // The shortest turn angle may be acheived by reversing the motor output direction
139  double angle1 = final - init;
140  double angle2 = final + wpi::math::pi - init;
141 
142  angle1 = Util::NegPiToPiRads(angle1);
143  angle2 = Util::NegPiToPiRads(angle2);
144 
145  // Choose the smallest angle and determine reverse flag
146  //TODO: FINISHED ROBOT TUNING
147  // Eventually prefer angle 1 always during high speed to prevent 180s
148  // if (fabs(angle1) <= 2 * fabs(angle2))
149  // {
150  bOutputReverse = false;
151 
152  return angle1;
153  // }
154  // else
155  // {
156  // bOutputReverse = true;
157 
158  // return angle2;
159  // }
160 }
static double NegPiToPiRads(double theta)
Definition: Util.cpp:35
static double ZeroTo2PiRads(double theta)
Definition: Util.cpp:15
meters_per_second_t SwerveModule::CalcMetersPerSec ( )
private

Calculate the MPS of the drive motor based on its current encoder tick velocity

Returns
Meters per second

Definition at line 162 of file SwerveModule.cpp.

References ModuleConstants::kDriveEncoderMetersPerSec, and m_driveMotor.

163 {
164  double ticksPer100ms = m_driveMotor.GetSelectedSensorVelocity();
165  return meters_per_second_t(kDriveEncoderMetersPerSec * ticksPer100ms);
166 }
constexpr double kDriveEncoderMetersPerSec
Definition: Constants.h:128
TalonFX m_driveMotor
Falon 500 that drives the pod.
Definition: SwerveModule.h:101
double SwerveModule::CalcTicksPer100Ms ( meters_per_second_t  speed)
private

Calculate drive motor encoder ticks based on the MPS

Parameters
speedMeters per second
Returns
Encoder ticks

Definition at line 168 of file SwerveModule.cpp.

References ModuleConstants::kDriveEncoderMetersPerSec.

169 {
170  return speed.to<double>() / kDriveEncoderMetersPerSec;
171 }
constexpr double kDriveEncoderMetersPerSec
Definition: Constants.h:128

Member Data Documentation

double SwerveModule::m_offset
private

The offset, in pulse widths, for syncing the relative encoder to the absolute encoder.

Definition at line 96 of file SwerveModule.h.

string SwerveModule::m_name
private

String used to identify each pod, used for SmartDashboard prints.

Definition at line 98 of file SwerveModule.h.

TalonFX SwerveModule::m_driveMotor
private

Falon 500 that drives the pod.

Definition at line 101 of file SwerveModule.h.

CANSparkMax SwerveModule::m_turningMotor
private

Definition at line 104 of file SwerveModule.h.

CANEncoder SwerveModule::m_turnRelativeEncoder
private
Initial value:
= m_turningMotor.GetAlternateEncoder(CANEncoder::AlternateEncoderType::kQuadrature,

Definition at line 105 of file SwerveModule.h.

CANPIDController SwerveModule::m_turnPIDController = m_turningMotor.GetPIDController()
private

Definition at line 107 of file SwerveModule.h.

PIDLoaderFalcon SwerveModule::m_drivePIDLoader
private

PID param loader for the TalonFX.

Definition at line 111 of file SwerveModule.h.

PIDLoaderNEO SwerveModule::m_turnPIDLoader
private

PID param loader for the CANSparkMax.

Definition at line 113 of file SwerveModule.h.

GetPulseWidthCallback SwerveModule::m_pulseWidthCallback
private

Callback used to determine the pulse width

Parameters
pwmChannelChannel to decide which absolute encoder's pulse width values are retrieved

Definition at line 117 of file SwerveModule.h.

CANifier::PWMChannel SwerveModule::m_pwmChannel
private

Definition at line 118 of file SwerveModule.h.

Timer SwerveModule::m_timer
private

Timer used to sync absolute and relative encoders on robot turn on.

Definition at line 121 of file SwerveModule.h.


The documentation for this class was generated from the following files: