1515import edu .wpi .first .math .kinematics .SwerveModulePosition ;
1616import edu .wpi .first .math .kinematics .SwerveModuleState ;
1717import edu .wpi .first .math .trajectory .TrapezoidProfile ;
18+ import edu .wpi .first .util .sendable .Sendable ;
19+ import edu .wpi .first .util .sendable .SendableBuilder ;
20+ import edu .wpi .first .util .sendable .SendableRegistry ;
1821import edu .wpi .first .wpilibj .Timer ;
1922import edu .wpi .first .wpilibj .smartdashboard .SmartDashboard ;
2023
2124/**
2225 * A class that stores all the variables and methods applicaple to a single swerve module,
2326 * such as moving, getting encoder values, or configuring PID.
2427 */
25- public class SwerveModule {
28+ public class SwerveModule implements Sendable {
2629 public enum ModuleType {FL , FR , BL , BR };
2730
2831 private SwerveConfig config ;
2932 private ModuleType type ;
30- private String moduleString ;
3133 private CANSparkMax drive , turn ;
3234 private CANCoder turnEncoder ;
3335 private PIDController drivePIDController ;
3436 private ProfiledPIDController turnPIDController ;
3537 private TrapezoidProfile .Constraints turnConstraints ;
36- private double driveModifier , maxSpeed , turnZero ;
38+ private double driveModifier , turnZero ;
3739 private Supplier <Float > pitchDegSupplier , rollDegSupplier ;
3840 private boolean reversed ;
3941 private Timer timer ;
4042 private SimpleMotorFeedforward forwardSimpleMotorFF , backwardSimpleMotorFF , turnSimpleMotorFeedforward ;
41- private double lastAngle , maxAchievableTurnVelocityDps , maxAchievableTurnAccelerationMps2 , turnToleranceDeg ;
43+ private double lastAngle , maxAchievableTurnVelocityDps , maxAchievableTurnAccelerationMps2 , turnToleranceDeg , angleDiff ;
4244
4345 public SwerveModule (SwerveConfig config , ModuleType type , CANSparkMax drive , CANSparkMax turn , CANCoder turnEncoder , double driveModifier ,
44- double maxSpeed , int arrIndex , Supplier <Float > pitchDegSupplier , Supplier <Float > rollDegSupplier ) {
46+ int arrIndex , Supplier <Float > pitchDegSupplier , Supplier <Float > rollDegSupplier ) {
4547 //SmartDashboard.putNumber("Target Angle (deg)", 0.0);
4648 this .timer = new Timer ();
4749 timer .start ();
@@ -50,21 +52,6 @@ public SwerveModule(SwerveConfig config, ModuleType type, CANSparkMax drive, CAN
5052 this .type = type ;
5153 this .drive = drive ;
5254
53- switch (type ) {
54- case FL :
55- moduleString = "FL" ;
56- break ;
57- case FR :
58- moduleString = "FR" ;
59- break ;
60- case BL :
61- moduleString = "BL" ;
62- break ;
63- case BR :
64- moduleString = "BR" ;
65- break ;
66- }
67-
6855 double positionConstant = config .wheelDiameterMeters * Math .PI / config .driveGearing ;
6956 drive .setInverted (config .driveInversion [arrIndex ]);
7057 drive .getEncoder ().setPositionConversionFactor (positionConstant );
@@ -77,7 +64,7 @@ public SwerveModule(SwerveConfig config, ModuleType type, CANSparkMax drive, CAN
7764 final double neoFreeCurrentAmps = 1.3 ;
7865 final double neoStallCurrentAmps = 166 ;
7966 double currentLimitAmps = neoFreeCurrentAmps + 2 *motorTorqueLimitNewtonMeters / neoStallTorqueNewtonMeters * (neoStallCurrentAmps -neoFreeCurrentAmps );
80- SmartDashboard .putNumber (moduleString + " current limit (amps)" , currentLimitAmps );
67+ SmartDashboard .putNumber (type . toString () + " current limit (amps)" , currentLimitAmps );
8168 drive .setSmartCurrentLimit ((int )Math .min (50 , currentLimitAmps ));
8269
8370 this .forwardSimpleMotorFF = new SimpleMotorFeedforward (config .kForwardVolts [arrIndex ],
@@ -121,22 +108,27 @@ public SwerveModule(SwerveConfig config, ModuleType type, CANSparkMax drive, CAN
121108 this .turnEncoder .configAbsoluteSensorRange (AbsoluteSensorRange .Signed_PlusMinus180 );
122109
123110 this .driveModifier = driveModifier ;
124- this .maxSpeed = maxSpeed ;
125111 this .reversed = config .reversed [arrIndex ];
126112 this .turnZero = config .turnZero [arrIndex ];
127113
128114 turnPIDController .reset (getModuleAngle ());
129115
130116 this .rollDegSupplier = rollDegSupplier ;
131117 this .pitchDegSupplier = pitchDegSupplier ;
118+
119+ SendableRegistry .addLW (this , "SweverModule" , type .toString ());
120+ }
121+
122+ public ModuleType getType () {
123+ return type ;
132124 }
133125
134126 private double prevTurnVelocity = 0 ;
135127 public void periodic () {
136128 double measuredAngleDegs = getModuleAngle ();
137129 TrapezoidProfile .State goal = turnPIDController .getGoal ();
138130 goal = new TrapezoidProfile .State (goal .position , goal .velocity );
139-
131+
140132 double period = turnPIDController .getPeriod ();
141133 double optimalTurnVelocityDps = Math .abs (MathUtil .inputModulus (goal .position -measuredAngleDegs , -180 , 180 ))/period ;
142134 setMaxTurnVelocity (Math .min (maxAchievableTurnVelocityDps , optimalTurnVelocityDps ));
@@ -148,9 +140,8 @@ public void periodic() {
148140 turn .setVoltage (MathUtil .clamp (turnVolts , -12.0 , 12.0 ));
149141 } else {
150142 turn .setVoltage (turnSimpleMotorFeedforward .calculate (goal .velocity ));
151- }
143+ }
152144 prevTurnVelocity = state .velocity ;
153- SmartDashboard .putNumber (moduleString + " error (deg)" , turnPIDController .getPositionError ());
154145 }
155146
156147 /**
@@ -193,8 +184,6 @@ private void setSpeed(double speedMps) {
193184 // Compute desired and actual speeds in m/s
194185 double desiredSpeed = speedMps * driveModifier ;
195186 double actualSpeed = getCurrentSpeed ();
196- SmartDashboard .putNumber (moduleString + " Desired Speed (mps)" , desiredSpeed );
197- SmartDashboard .putNumber (moduleString + " Actual Speed (mps)" , actualSpeed );
198187 double targetVoltage = (actualSpeed >= 0 ? forwardSimpleMotorFF :
199188 backwardSimpleMotorFF ).calculate (desiredSpeed , calculateAntiGravitationalA (pitchDegSupplier .get (), rollDegSupplier .get ()));//clippedAcceleration);
200189
@@ -216,12 +205,12 @@ private void setAngle(double angle) {
216205 double maxDeltaTheta = Math .asin (deltaTime *config .autoCentripetalAccel /(Math .abs (getCurrentSpeed ())+0.0001 ));
217206 setMaxTurnVelocity (maxDeltaTheta *180 /Math .PI );
218207 //SmartDashboard.putNumber(moduleString + "Target Angle:", 360 * angle * (reversed ? -1 : 1));
219-
208+
220209 // Find the minimum distance to travel from lastAngle to angle and determine the
221210 // correct direction to trvel the minimum distance. This is used in order to accurately
222211 // calculate the goal velocity.
223- double angleDiff = MathUtil .inputModulus (angle - lastAngle , -180 , 180 );
224- SmartDashboard .putNumber (moduleString + " angleDiff (deg)" , angleDiff );
212+ angleDiff = MathUtil .inputModulus (angle - lastAngle , -180 , 180 );
213+ // SmartDashboard.putNumber(moduleString + " angleDiff (deg)", angleDiff);
225214
226215 turnPIDController .setGoal (new TrapezoidProfile .State (angle * (reversed ? -1 : 1 ), 0 ));
227216 lastAngle = angle ;
@@ -261,8 +250,12 @@ public double getCurrentSpeed() {
261250
262251 /**
263252 * Updates SmartDashboard with information about this module.
253+ *
254+ * @deprecated Put this Sendable to SmartDashboard instead
264255 */
256+ @ Deprecated
265257 public void updateSmartDashboard () {
258+ String moduleString = type .toString ();
266259 // Display the position of the quadrature encoder.
267260 SmartDashboard .putNumber (moduleString + " Incremental Position" , turnEncoder .getPosition ());
268261 // Display the position of the analog encoder.
@@ -281,7 +274,7 @@ public void updateSmartDashboard() {
281274 SmartDashboard .putNumber (moduleString + "Antigravitational Acceleration" , calculateAntiGravitationalA (pitchDegSupplier .get (), rollDegSupplier .get ()));
282275 SmartDashboard .putBoolean (moduleString + " Turn is at Goal" , turnPIDController .atGoal ());
283276 }
284-
277+
285278 public void toggleMode () {
286279 if (drive .getIdleMode () == IdleMode .kBrake && turn .getIdleMode () == IdleMode .kCoast ) coast ();
287280 else brake ();
@@ -301,4 +294,26 @@ public void setMaxTurnVelocity(double maxVel) {
301294 turnConstraints = new TrapezoidProfile .Constraints (maxVel , turnConstraints .maxAcceleration );
302295 turnPIDController .setConstraints (turnConstraints );
303296 }
297+
298+ @ Override
299+ public void initSendable (SendableBuilder builder ) {
300+ builder .setActuator (true );
301+ builder .setSafeState (() -> setSpeed (0 ));
302+ builder .setSmartDashboardType ("SwerveModule" );
303+ builder .addDoubleProperty ("Incremental Position" , turnEncoder ::getPosition , null );
304+ builder .addDoubleProperty ("Absolute Angle (deg)" , turnEncoder ::getAbsolutePosition , null );
305+ builder .addDoubleProperty ("Turn Measured Pos (deg)" , this ::getModuleAngle , null );
306+ builder .addDoubleProperty ("Encoder Position" , drive .getEncoder ()::getPosition , null );
307+ // Display the speed that the robot thinks it is travelling at.
308+ builder .addDoubleProperty ("Current Speed" , this ::getCurrentSpeed , null );
309+ builder .addDoubleProperty ("Turn Setpoint Pos (deg)" , () -> turnPIDController .getSetpoint ().position , null );
310+ builder .addDoubleProperty ("Turn Setpoint Vel (dps)" , () -> turnPIDController .getSetpoint ().velocity , null );
311+ builder .addDoubleProperty ("Turn Goal Pos (deg)" , () -> turnPIDController .getGoal ().position , null );
312+ builder .addDoubleProperty ("Turn Goal Vel (dps)" , () -> turnPIDController .getGoal ().velocity , null );
313+ builder .addDoubleProperty ("Antigravitational Acceleration" , () -> calculateAntiGravitationalA (pitchDegSupplier .get (), rollDegSupplier .get ()), null );
314+ builder .addBooleanProperty ("Turn is at Goal" , turnPIDController ::atGoal , null );
315+ builder .addDoubleProperty ("Error (deg)" , turnPIDController ::getPositionError , null );
316+ builder .addDoubleProperty ("Desired Speed (mps)" , drivePIDController ::getSetpoint , null );
317+ builder .addDoubleProperty ("Angle Diff (deg)" , () -> angleDiff , null );
318+ }
304319}
0 commit comments