1+ // Copyright (c) 2024 FRC 6328
2+ // http://github.com/Mechanical-Advantage
3+ //
4+ // Use of this source code is governed by an MIT-style
5+ // license that can be found in the LICENSE file at
6+ // the root directory of this project.
7+
8+ package frc .trigon .robot .commands ;
9+
10+ import edu .wpi .first .math .filter .SlewRateLimiter ;
11+ import edu .wpi .first .math .geometry .Translation2d ;
12+ import edu .wpi .first .wpilibj2 .command .Command ;
13+ import edu .wpi .first .wpilibj2 .command .SubsystemBase ;
14+ import org .littletonrobotics .junction .Logger ;
15+ import org .littletonrobotics .junction .networktables .LoggedDashboardBoolean ;
16+ import org .littletonrobotics .junction .networktables .LoggedDashboardNumber ;
17+
18+ import java .util .Arrays ;
19+ import java .util .function .DoubleConsumer ;
20+ import java .util .function .DoubleSupplier ;
21+ import java .util .function .Supplier ;
22+
23+ public class WheelRadiusCharacterizationCommand extends Command {
24+ private static final LoggedDashboardNumber CHARACTERIZATION_SPEED = new LoggedDashboardNumber ("WheelRadiusCharacterization/SpeedRadiansPerSecond" , 1 );
25+ private static final LoggedDashboardNumber ROTATION_RATE_LIMIT = new LoggedDashboardNumber ("WheelRadiusCharacterization/RotationRateLimit" , 1 );
26+ private static final LoggedDashboardBoolean SHOULD_MOVE_CLOCKWISE = new LoggedDashboardBoolean ("WheelRadiusCharacterization/ShouldMoveClockwise" , false );
27+
28+ private final double [] wheelDistancesFromCenterMeters ;
29+ private final Supplier <double []> wheelPositionsRadiansSupplier ;
30+ private final DoubleSupplier gyroYawRadiansSupplier ;
31+ private final DoubleConsumer runWheelRadiusCharacterization ;
32+
33+ private SlewRateLimiter rotationSlewRateLimiter = new SlewRateLimiter (ROTATION_RATE_LIMIT .get ());
34+ private double startingGyroYawRadians ;
35+ private double accumulatedGyroYawRadians ;
36+ private double [] startingWheelPositions ;
37+ private double driveWheelsRadius ;
38+
39+ public WheelRadiusCharacterizationCommand (Translation2d [] wheelDistancesFromCenterMeters , Supplier <double []> wheelPositionsRadiansSupplier ,
40+ DoubleSupplier gyroYawRadiansSupplier , DoubleConsumer runWheelRadiusCharacterization , SubsystemBase requirement
41+ ) {
42+ this .wheelDistancesFromCenterMeters = Arrays .stream (wheelDistancesFromCenterMeters ).mapToDouble (Translation2d ::getNorm ).toArray ();
43+ this .wheelPositionsRadiansSupplier = wheelPositionsRadiansSupplier ;
44+ this .gyroYawRadiansSupplier = gyroYawRadiansSupplier ;
45+ this .runWheelRadiusCharacterization = runWheelRadiusCharacterization ;
46+ addRequirements (requirement );
47+ }
48+
49+ public WheelRadiusCharacterizationCommand (double [] wheelDistancesFromCenterMeters , Supplier <double []> wheelPositionsRadiansSupplier ,
50+ DoubleSupplier gyroYawRadiansSupplier , DoubleConsumer runWheelRadiusCharacterization , SubsystemBase requirement
51+ ) {
52+ this .wheelDistancesFromCenterMeters = wheelDistancesFromCenterMeters ;
53+ this .wheelPositionsRadiansSupplier = wheelPositionsRadiansSupplier ;
54+ this .gyroYawRadiansSupplier = gyroYawRadiansSupplier ;
55+ this .runWheelRadiusCharacterization = runWheelRadiusCharacterization ;
56+ addRequirements (requirement );
57+ }
58+
59+ @ Override
60+ public void initialize () {
61+ configureStartingStats ();
62+ }
63+
64+ @ Override
65+ public void execute () {
66+ driveMotors ();
67+
68+ accumulatedGyroYawRadians = getAccumulatedGyroYaw ();
69+ driveWheelsRadius = calculateDriveWheelRadius ();
70+
71+ Logger .recordOutput ("WheelRadiusCharacterization/AccumulatedGyroYawRadians" , accumulatedGyroYawRadians );
72+ Logger .recordOutput ("RadiusCharacterization/DriveWheelRadius" , driveWheelsRadius );
73+ }
74+
75+ @ Override
76+ public void end (boolean interrupted ) {
77+ printResults ();
78+ }
79+
80+ private void configureStartingStats () {
81+ startingGyroYawRadians = gyroYawRadiansSupplier .getAsDouble ();
82+ startingWheelPositions = wheelPositionsRadiansSupplier .get ();
83+ accumulatedGyroYawRadians = 0.0 ;
84+
85+ rotationSlewRateLimiter = new SlewRateLimiter (ROTATION_RATE_LIMIT .get ());
86+ rotationSlewRateLimiter .reset (0 );
87+ }
88+
89+ private void driveMotors () {
90+ runWheelRadiusCharacterization .accept (rotationSlewRateLimiter .calculate (getRotationDirection () * CHARACTERIZATION_SPEED .get ()));
91+ }
92+
93+ private double getAccumulatedGyroYaw () {
94+ return Math .abs (startingGyroYawRadians - gyroYawRadiansSupplier .getAsDouble ());
95+ }
96+
97+ private double calculateDriveWheelRadius () {
98+ driveWheelsRadius = 0 ;
99+ final double [] wheelPositionsRadians = wheelPositionsRadiansSupplier .get ();
100+
101+ for (int i = 0 ; i < 4 ; i ++) {
102+ final double accumulatedWheelRadians = Math .abs (wheelPositionsRadians [i ] - startingWheelPositions [i ]);
103+ driveWheelsRadius += (accumulatedGyroYawRadians * wheelDistancesFromCenterMeters [i ]) / accumulatedWheelRadians ;
104+ Logger .recordOutput ("RadiusCharacterization/AccumulatedWheelRadians" + i , accumulatedWheelRadians );
105+ }
106+
107+ return driveWheelsRadius /= 4 ;
108+ }
109+
110+ private void printResults () {
111+ if (accumulatedGyroYawRadians <= Math .PI * 2.0 )
112+ System .out .println ("Not enough data for characterization" );
113+ else
114+ System .out .println ("Drive Wheel Radius: " + driveWheelsRadius + " meters" );
115+ }
116+
117+ private int getRotationDirection () {
118+ return SHOULD_MOVE_CLOCKWISE .get () ? -1 : 1 ;
119+ }
120+ }
0 commit comments