Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions src/main/java/frc/robot/Controls.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import frc.robot.util.ScoringMode;
import frc.robot.util.ScoringType;
import frc.robot.util.SoloScoringMode;
import frc.robot.util.WheelRadiusCharacterization;
import java.util.function.BooleanSupplier;

public class Controls {
Expand Down Expand Up @@ -1112,13 +1113,17 @@ private void configureSoloControllerBindings() {
: Commands.none())
.withName("Manual Coral Intake"));
// Ground Intake Hold out
// soloController
// .povUp()
// .whileTrue(
// s.groundArm
// .moveToPosition(GroundArm.GROUND_POSITION)
// .andThen(Commands.idle())
// .withName("ground up position"));
Comment on lines +1116 to +1122

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This block of code is commented out. If it's no longer needed, it should be removed to improve code clarity. If it's being temporarily replaced for testing, it's better to use version control to switch between versions rather than leaving commented-out code.

soloController
.povUp()
.whileTrue(
s.groundArm
.moveToPosition(GroundArm.GROUND_POSITION)
.andThen(Commands.idle())
.withName("ground up position"));
.onTrue(
WheelRadiusCharacterization.wheelRadiusCharacterizationCommand(s.drivebaseSubsystem));
// Arm manual
soloController
.rightStick()
Expand Down
9 changes: 8 additions & 1 deletion src/main/java/frc/robot/Robot.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import frc.robot.util.BuildInfo;
import frc.robot.util.MatchTab;
import frc.robot.util.RobotType;
import frc.robot.util.WheelRadiusCharacterization;

public class Robot extends TimedRobot {
/** Singleton Stuff */
Expand Down Expand Up @@ -144,12 +145,18 @@ public void disabledExit() {
@Override
public void autonomousInit() {
Shuffleboard.startRecording();
if (SubsystemConstants.DRIVEBASE_ENABLED && AutoLogic.getSelectedAuto() != null) {
if (SubsystemConstants.DRIVEBASE_ENABLED
&& AutoLogic.getSelectedAuto() != null
&& !AutoLogic.RUN_MEASUREMENT_AUTO) {
AutoLogic.getSelectedAuto().schedule();
}
if (subsystems.climbPivotSubsystem != null) {
subsystems.climbPivotSubsystem.moveCompleteFalse();
}
if (SubsystemConstants.DRIVEBASE_ENABLED && AutoLogic.RUN_MEASUREMENT_AUTO) {
WheelRadiusCharacterization.wheelRadiusCharacterizationCommand(subsystems.drivebaseSubsystem)
.schedule();
}
}

@Override
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/frc/robot/generated/CompTunerConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public class CompTunerConstants {

private static final double kDriveGearRatio = 5.357142857142857;
private static final double kSteerGearRatio = 18.75;
private static final Distance kWheelRadius = Inches.of(2 * 21 / (22.1 * 0.97));
public static final Distance kWheelRadius = Inches.of(2 * 21 / (22.1 * 0.97));

private static final boolean kInvertLeftSide = false;
private static final boolean kInvertRightSide = true;
Expand Down
1 change: 1 addition & 0 deletions src/main/java/frc/robot/subsystems/auto/AutoLogic.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public class AutoLogic {
public static Robot r = Robot.getInstance();
public static final Subsystems s = r.subsystems;
public static final Controls controls = r.controls;
public static final boolean RUN_MEASUREMENT_AUTO = true;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The RUN_MEASUREMENT_AUTO flag is hardcoded to true. This is risky as it will cause the characterization routine to run instead of the selected autonomous mode every time the robot is in auto. This could lead to unexpected behavior during a match. It's highly recommended to set this to false by default and use a Shuffleboard toggle to enable it only when needed for testing.

Suggested change
public static final boolean RUN_MEASUREMENT_AUTO = true;
public static final boolean RUN_MEASUREMENT_AUTO = false;


public static enum StartPosition {
FAR_LEFT_CAGE(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.Subsystem;
import edu.wpi.first.wpilibj2.command.sysid.SysIdRoutine;
import frc.robot.generated.CompTunerConstants;
import java.util.function.Supplier;

/**
Expand Down Expand Up @@ -261,4 +262,13 @@ public Command coastMotors() {
public void brakeMotors() {
configNeutralMode(NeutralModeValue.Brake);
}

public double[] getWheelRotations() {
double wheelCircumference = 2 * Math.PI * CompTunerConstants.kWheelRadius.abs(Meter);
double[] values = new double[4];
for (int i = 0; i < 4; i++) {
values[i] = getState().ModulePositions[i].distanceMeters / wheelCircumference;
}
return values;
}
}
116 changes: 116 additions & 0 deletions src/main/java/frc/robot/util/WheelRadiusCharacterization.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package frc.robot.util;

import com.ctre.phoenix6.swerve.SwerveRequest;
import edu.wpi.first.math.filter.SlewRateLimiter;
import edu.wpi.first.math.geometry.Rotation2d;
import edu.wpi.first.math.kinematics.ChassisSpeeds;
import edu.wpi.first.math.util.Units;
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.Commands;
import frc.robot.generated.CompTunerConstants;
import frc.robot.subsystems.drivebase.CommandSwerveDrivetrain;
import java.text.DecimalFormat;
import java.text.NumberFormat;

public class WheelRadiusCharacterization {
private static final double WHEEL_RADIUS_MAX_VELOCITY = 4; // Rad/Sec
private static final double WHEEL_RADIUS_RAMP_RATE = 0.5; // Rad/Sec^2
public static final double DRIVE_BASE_RADIUS =
Math.max(
Math.max(
Math.hypot(
CompTunerConstants.FrontLeft.LocationX, CompTunerConstants.FrontLeft.LocationY),
Math.hypot(
CompTunerConstants.FrontRight.LocationX,
CompTunerConstants.FrontRight.LocationY)),
Math.max(
Math.hypot(
CompTunerConstants.BackLeft.LocationX, CompTunerConstants.BackLeft.LocationY),
Math.hypot(
CompTunerConstants.BackRight.LocationX, CompTunerConstants.BackRight.LocationY)));
Comment on lines +18 to +30

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The calculation for DRIVE_BASE_RADIUS is correct, but the deeply nested Math.max calls make it difficult to read. This can be refactored using a Java Stream for improved readability and maintainability.

  public static final double DRIVE_BASE_RADIUS =
      java.util.stream.Stream.of(
              CompTunerConstants.FrontLeft,
              CompTunerConstants.FrontRight,
              CompTunerConstants.BackLeft,
              CompTunerConstants.BackRight)
          .mapToDouble(c -> Math.hypot(c.LocationX, c.LocationY))
          .max()
          .orElse(0.0);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is a java Stream? and what does .max() do?

private static final NumberFormat FORMATTER = new DecimalFormat("#0.000");

// get the wheel rotation positions of the swerve modules
public static double[] getWheelRadiusCharacterizationPositions(CommandSwerveDrivetrain drive) {
return drive.getWheelRotations();
}

public static Command wheelRadiusCharacterizationCommand(CommandSwerveDrivetrain drive) {
SlewRateLimiter limiter = new SlewRateLimiter(WHEEL_RADIUS_RAMP_RATE);
WheelRadiusCharacterizationState state = new WheelRadiusCharacterizationState();
return Commands.parallel(
// Drive control sequence
Commands.sequence(
// Reset acceleration limiter
Commands.runOnce(
() -> {
limiter.reset(0.0);
}),

// Turn in place, accelerating up to full speed
Commands.run(
() -> {
double speed = limiter.calculate(WHEEL_RADIUS_MAX_VELOCITY);
System.out.println(speed);
// drive.runVelocity(new ChassisSpeeds(0.0, 0.0, speed));
SwerveRequest driveRequest =
new SwerveRequest.ApplyRobotSpeeds()
.withSpeeds(new ChassisSpeeds(0.0, 0.0, speed));
drive.setControl(driveRequest);
},
drive)),

// Measurement sequence
Commands.sequence(
// Wait for modules to fully orient before starting measurement
Commands.waitSeconds(1.0),

// Record starting measurement
Commands.runOnce(
() -> {
state.positions = getWheelRadiusCharacterizationPositions(drive);
state.lastAngle = drive.getState().Pose.getRotation();
state.gyroDelta = 0.0;
}),

// Update gyro delta
Commands.run(
() -> {
var rotation = drive.getState().Pose.getRotation();
state.gyroDelta += Math.abs(rotation.minus(state.lastAngle).getRadians());
state.lastAngle = rotation;
})

// When cancelled, calculate and print results
.finallyDo(
() -> {
double[] positions = getWheelRadiusCharacterizationPositions(drive);
double wheelDelta = 0.0;
for (int i = 0; i < 4; i++) {
wheelDelta += Math.abs(positions[i] - state.positions[i]) / 4.0;
}
wheelDelta *= 2 * Math.PI;
double wheelRadius = (state.gyroDelta * DRIVE_BASE_RADIUS) / wheelDelta;

System.out.println(
"********** Wheel Radius Characterization Results **********");
System.out.println(
"\tWheel Delta: " + FORMATTER.format(wheelDelta) + " radians");
System.out.println(
"\tGyro Delta: " + FORMATTER.format(state.gyroDelta) + " radians");
System.out.println(
"\tWheel Radius: "
+ FORMATTER.format(wheelRadius)
+ " meters, "
+ FORMATTER.format(Units.metersToInches(wheelRadius))
+ " inches");
})))
.withName("wheel radius characterization");
}

private static class WheelRadiusCharacterizationState {
double[] positions = new double[4];
Rotation2d lastAngle = Rotation2d.kZero;
double gyroDelta = 0.0;
}
}