-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSwerveModule.java
More file actions
117 lines (95 loc) · 4.94 KB
/
SwerveModule.java
File metadata and controls
117 lines (95 loc) · 4.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package frc.robot;
import com.ctre.phoenix6.controls.DutyCycleOut;
import com.ctre.phoenix6.controls.PositionVoltage;
import com.ctre.phoenix6.controls.VelocityVoltage;
import com.ctre.phoenix6.hardware.CANcoder;
import com.ctre.phoenix6.hardware.TalonFX;
import edu.wpi.first.math.controller.SimpleMotorFeedforward;
import edu.wpi.first.math.geometry.Rotation2d;
import edu.wpi.first.math.kinematics.SwerveModulePosition;
import edu.wpi.first.math.kinematics.SwerveModuleState;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import frc.lib.math.Conversions;
import frc.lib.util.SwerveModuleConstants;
public class SwerveModule {
public int moduleNumber;
private Rotation2d angleOffset;
/* used to track drive acceleration */
private double driveAccelerationMPS = 0.0;
private double drivePreviousTimestamp = 0.0;
private double drivePreviousVelocityMPS = 0.0;
private TalonFX mAngleMotor;
private TalonFX mDriveMotor;
private CANcoder angleEncoder;
private final SimpleMotorFeedforward driveFeedForward = new SimpleMotorFeedforward(Constants.Swerve.driveKS,
Constants.Swerve.driveKV, Constants.Swerve.driveKA);
/* drive motor control requests */
private final DutyCycleOut driveDutyCycle = new DutyCycleOut(0);
private final VelocityVoltage driveVelocity = new VelocityVoltage(0);
/* angle motor control requests */
private final PositionVoltage anglePosition = new PositionVoltage(0);
public SwerveModule(int moduleNumber, SwerveModuleConstants moduleConstants) {
this.moduleNumber = moduleNumber;
this.angleOffset = moduleConstants.angleOffset;
/* Angle Encoder Config */
angleEncoder = new CANcoder(moduleConstants.cancoderID);
angleEncoder.getConfigurator().apply(Robot.ctreConfigs.swerveCANcoderConfig);
/* Angle Motor Config */
mAngleMotor = new TalonFX(moduleConstants.angleMotorID);
mAngleMotor.getConfigurator().apply(Robot.ctreConfigs.swerveAngleFXConfig);
resetToAbsolute();
/* Drive Motor Config */
mDriveMotor = new TalonFX(moduleConstants.driveMotorID);
mDriveMotor.getConfigurator().apply(Robot.ctreConfigs.swerveDriveFXConfig);
mDriveMotor.getConfigurator().setPosition(0.0);
}
public void setDesiredState(SwerveModuleState desiredState, boolean isOpenLoop) {
desiredState = SwerveModuleState.optimize(desiredState, getState().angle);
mAngleMotor.setControl(anglePosition.withPosition(desiredState.angle.getRotations()));
setSpeed(desiredState, isOpenLoop);
}
private void setSpeed(SwerveModuleState desiredState, boolean isOpenLoop) {
if (isOpenLoop) {
driveDutyCycle.Output = desiredState.speedMetersPerSecond / Constants.Swerve.maxSpeed;
mDriveMotor.setControl(driveDutyCycle);
} else {
driveVelocity.Velocity = Conversions.MPSToRPS(desiredState.speedMetersPerSecond,
Constants.Swerve.wheelCircumference);
driveVelocity.FeedForward = driveFeedForward.calculate(desiredState.speedMetersPerSecond);
mDriveMotor.setControl(driveVelocity);
}
}
public Rotation2d getCANcoder() {
return Rotation2d.fromRotations(angleEncoder.getAbsolutePosition().getValueAsDouble());
}
public void resetToAbsolute() {
double absolutePosition = getCANcoder().getRotations() - angleOffset.getRotations();
mAngleMotor.setPosition(absolutePosition);
}
public SwerveModuleState getState() {
return new SwerveModuleState(
Conversions.RPSToMPS(mDriveMotor.getVelocity().getValueAsDouble(), Constants.Swerve.wheelCircumference),
Rotation2d.fromRotations(mAngleMotor.getPosition().getValueAsDouble()));
}
public SwerveModulePosition getPosition() {
return new SwerveModulePosition(
Conversions.rotationsToMeters(mDriveMotor.getPosition().getValueAsDouble(),
Constants.Swerve.wheelCircumference),
Rotation2d.fromRotations(mAngleMotor.getPosition().getValueAsDouble()));
}
/**
* Called from Swerve Drive subsystem periodic
*/
public void update() {
SmartDashboard.putNumber("Mod " + moduleNumber + " CANcoder", getCANcoder().getDegrees());
SmartDashboard.putNumber("Mod " + moduleNumber + " Angle", getPosition().angle.getDegrees());
SmartDashboard.putNumber("Mod " + moduleNumber + " Velocity", getState().speedMetersPerSecond);
// Log module data to AK
double timeBetweenUpdates = Timer.getFPGATimestamp() - this.drivePreviousTimestamp;
double currentVelocityMPS = getState().speedMetersPerSecond;
this.driveAccelerationMPS = (currentVelocityMPS - this.drivePreviousVelocityMPS) / timeBetweenUpdates;
this.drivePreviousVelocityMPS = currentVelocityMPS;
this.drivePreviousTimestamp = Timer.getFPGATimestamp();
}
}