Compare commits
2
Commits
af1095cf50
..
手搓
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
132b231c36 | ||
|
|
99a92af429 |
@@ -91,6 +91,93 @@
|
||||
"period": 0.06,
|
||||
"sort_options": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "HubActive",
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"width": 256.0,
|
||||
"height": 128.0,
|
||||
"type": "Boolean Box",
|
||||
"properties": {
|
||||
"topic": "/GameData2026/HubActive",
|
||||
"period": 0.06,
|
||||
"data_type": "boolean",
|
||||
"true_color": 4283215696,
|
||||
"false_color": 4294198070,
|
||||
"true_icon": "None",
|
||||
"false_icon": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "HubStatus",
|
||||
"x": 256.0,
|
||||
"y": 0.0,
|
||||
"width": 256.0,
|
||||
"height": 128.0,
|
||||
"type": "Text Display",
|
||||
"properties": {
|
||||
"topic": "/GameData2026/HubStatus",
|
||||
"period": 0.06,
|
||||
"data_type": "string",
|
||||
"show_submit_button": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "SecondsUntilHubOpens",
|
||||
"x": 0.0,
|
||||
"y": 128.0,
|
||||
"width": 256.0,
|
||||
"height": 128.0,
|
||||
"type": "Text Display",
|
||||
"properties": {
|
||||
"topic": "/GameData2026/SecondsUntilHubOpens",
|
||||
"period": 0.06,
|
||||
"data_type": "double",
|
||||
"show_submit_button": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Shift",
|
||||
"x": 256.0,
|
||||
"y": 128.0,
|
||||
"width": 256.0,
|
||||
"height": 128.0,
|
||||
"type": "Text Display",
|
||||
"properties": {
|
||||
"topic": "/GameData2026/Shift",
|
||||
"period": 0.06,
|
||||
"data_type": "string",
|
||||
"show_submit_button": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "FirstInactiveAlliance",
|
||||
"x": 0.0,
|
||||
"y": 256.0,
|
||||
"width": 256.0,
|
||||
"height": 128.0,
|
||||
"type": "Text Display",
|
||||
"properties": {
|
||||
"topic": "/GameData2026/FirstInactiveAlliance",
|
||||
"period": 0.06,
|
||||
"data_type": "string",
|
||||
"show_submit_button": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "MatchTime",
|
||||
"x": 256.0,
|
||||
"y": 256.0,
|
||||
"width": 256.0,
|
||||
"height": 128.0,
|
||||
"type": "Text Display",
|
||||
"properties": {
|
||||
"topic": "/GameData2026/MatchTime",
|
||||
"period": 0.06,
|
||||
"data_type": "double",
|
||||
"show_submit_button": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ public class Robot extends TimedRobot {
|
||||
public void robotPeriodic() {
|
||||
CommandScheduler.getInstance().run();
|
||||
m_robotContainer.tunerPeriodic();
|
||||
m_robotContainer.dashboardPeriodic();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import frc.robot.utils.LedBindings;
|
||||
import frc.robot.controls.ClimberControls;
|
||||
import frc.robot.controls.Autocommand;
|
||||
import frc.robot.subsystems.ClimberSubsystem;
|
||||
import frc.robot.utils.GameData2026;
|
||||
public class RobotContainer {
|
||||
|
||||
/* ====================== */
|
||||
@@ -63,6 +64,7 @@ public class RobotContainer {
|
||||
//private final ClimberControls climberControls = new ClimberControls(climberSubsystem, controllerupper);
|
||||
private final IntakerControls intakerControls = new IntakerControls(IntakerSubsystem, shooterSubsystem, controllerupper);
|
||||
private final DriveGainsTuner driveGainsTuner = new DriveGainsTuner(drivetrain);
|
||||
private final GameData2026 gameData2026 = new GameData2026();
|
||||
private ConfigTalonFXMotorTuner configFlywheelTuner = new ConfigTalonFXMotorTuner(shooterSubsystem.flywheelMotorLeft, "flywheel", Constants.Shooter.flyWheelSlot0Configs);
|
||||
private ConfigTalonFXMotorTuner configConveyorTuner = new ConfigTalonFXMotorTuner(shooterSubsystem.conveyorMotor, "conveyor", Constants.Shooter.conveyorSlot0Configs);
|
||||
private ConfigTalonFXSMotorTuner configBackboardTuner = new ConfigTalonFXSMotorTuner(shooterSubsystem.backboardMotor, "backboard", Constants.Shooter.backboardSlot0Configs);
|
||||
@@ -202,6 +204,10 @@ public class RobotContainer {
|
||||
shooterSubsystem.setRightFollowLeft();
|
||||
}
|
||||
|
||||
public void dashboardPeriodic() {
|
||||
gameData2026.periodic();
|
||||
}
|
||||
|
||||
// private void configueClimber() {
|
||||
// climberSubsystem.setDefaultCommand(climberControls.defaultClimberCommand());
|
||||
// }
|
||||
|
||||
@@ -24,14 +24,14 @@ public class TunerConstants {
|
||||
// The steer motor uses any SwerveModule.SteerRequestType control request with the
|
||||
// output type specified by SwerveModuleConstants.SteerMotorClosedLoopOutput
|
||||
private static final Slot0Configs steerGains = new Slot0Configs()
|
||||
.withKP(70).withKI(0).withKD(0.5)
|
||||
.withKP(100).withKI(0).withKD(0.5)
|
||||
.withKS(0.1).withKV(1.59).withKA(0)
|
||||
.withStaticFeedforwardSign(StaticFeedforwardSignValue.UseClosedLoopSign);
|
||||
// When using closed-loop control, the drive motor uses the control
|
||||
// output type specified by SwerveModuleConstants.DriveMotorClosedLoopOutput
|
||||
private static final Slot0Configs driveGains = new Slot0Configs()
|
||||
.withKP(0.01).withKI(0).withKD(0)
|
||||
.withKS(0.05).withKV(0.117);
|
||||
.withKP(0.1).withKI(0).withKD(0)
|
||||
.withKS(0).withKV(0.124);
|
||||
|
||||
// The closed-loop output type to use for the steer motors;
|
||||
// This affects the PID/FF gains for the steer motors
|
||||
@@ -42,7 +42,7 @@ public class TunerConstants {
|
||||
|
||||
// The type of motor used for the drive motor
|
||||
private static final DriveMotorArrangement kDriveMotorType = DriveMotorArrangement.TalonFX_Integrated;
|
||||
// The type of motor used for the drive motor
|
||||
// The type of motor used for the steer motor
|
||||
private static final SteerMotorArrangement kSteerMotorType = SteerMotorArrangement.TalonFX_Integrated;
|
||||
|
||||
// The remote sensor feedback type to use for the steer motors;
|
||||
@@ -55,7 +55,14 @@ public class TunerConstants {
|
||||
|
||||
// Initial configs for the drive and steer motors and the azimuth encoder; these cannot be null.
|
||||
// Some configs will be overwritten; check the `with*InitialConfigs()` API documentation.
|
||||
private static final TalonFXConfiguration driveInitialConfigs = new TalonFXConfiguration();
|
||||
private static final TalonFXConfiguration driveInitialConfigs = new TalonFXConfiguration()
|
||||
.withCurrentLimits(
|
||||
new CurrentLimitsConfigs()
|
||||
// Default supply current limit is 70 A, but it can be lowered to avoid brownouts.
|
||||
// Supply current limits can be larger than the breaker current rating.
|
||||
.withSupplyCurrentLimit(Amps.of(70))
|
||||
.withSupplyCurrentLimitEnable(true)
|
||||
);
|
||||
private static final TalonFXConfiguration steerInitialConfigs = new TalonFXConfiguration()
|
||||
.withCurrentLimits(
|
||||
new CurrentLimitsConfigs()
|
||||
@@ -66,23 +73,14 @@ public class TunerConstants {
|
||||
);
|
||||
private static final CANcoderConfiguration encoderInitialConfigs = new CANcoderConfiguration();
|
||||
// Configs for the Pigeon 2; leave this null to skip applying Pigeon 2 configs
|
||||
private static final Pigeon2Configuration pigeonConfigs =
|
||||
new Pigeon2Configuration()
|
||||
.withGyroTrim(
|
||||
new GyroTrimConfigs()
|
||||
.withGyroScalarZ(-5.0)
|
||||
)
|
||||
.withPigeon2Features(
|
||||
new Pigeon2FeaturesConfigs()
|
||||
.withEnableCompass(false)
|
||||
);
|
||||
|
||||
private static final Pigeon2Configuration pigeonConfigs = null;
|
||||
|
||||
// CAN bus that the devices are located on;
|
||||
// All swerve devices must share the same CAN bus
|
||||
public static final CANBus kCANBus = new CANBus("", "./logs/example.hoot");
|
||||
|
||||
// Theoretical free speed (m/s) at 12 V applied output;
|
||||
// Measured robot speed (m/s) at 12 V applied output;
|
||||
// This is NOT the desired max robot speed - see MaxSpeed in RobotContainer instead;
|
||||
// This needs to be tuned to your individual robot
|
||||
public static final LinearVelocity kSpeedAt12Volts = MetersPerSecond.of(4.73);
|
||||
|
||||
@@ -101,7 +99,7 @@ public class TunerConstants {
|
||||
|
||||
// These are only used for simulation
|
||||
private static final MomentOfInertia kSteerInertia = KilogramSquareMeters.of(0.01);
|
||||
private static final MomentOfInertia kDriveInertia = KilogramSquareMeters.of(0.01);
|
||||
private static final MomentOfInertia kDriveInertia = KilogramSquareMeters.of(0.035);
|
||||
// Simulated voltage necessary to overcome friction
|
||||
private static final Voltage kSteerFrictionVoltage = Volts.of(0.2);
|
||||
private static final Voltage kDriveFrictionVoltage = Volts.of(0.2);
|
||||
@@ -136,10 +134,10 @@ public class TunerConstants {
|
||||
|
||||
|
||||
// Front Left
|
||||
private static final int kFrontLeftDriveMotorId = 11;
|
||||
private static final int kFrontLeftSteerMotorId = 12;
|
||||
private static final int kFrontLeftEncoderId = 13;
|
||||
private static final Angle kFrontLeftEncoderOffset = Rotations.of(-0.412841796875);
|
||||
private static final int kFrontLeftDriveMotorId = 1;
|
||||
private static final int kFrontLeftSteerMotorId = 2;
|
||||
private static final int kFrontLeftEncoderId = 3;
|
||||
private static final Angle kFrontLeftEncoderOffset = Rotations.of(-0.18115234375);
|
||||
private static final boolean kFrontLeftSteerMotorInverted = false;
|
||||
private static final boolean kFrontLeftEncoderInverted = false;
|
||||
|
||||
@@ -147,10 +145,10 @@ public class TunerConstants {
|
||||
private static final Distance kFrontLeftYPos = Inches.of(11.375);
|
||||
|
||||
// Front Right
|
||||
private static final int kFrontRightDriveMotorId = 21;
|
||||
private static final int kFrontRightSteerMotorId = 22;
|
||||
private static final int kFrontRightEncoderId = 23;
|
||||
private static final Angle kFrontRightEncoderOffset = Rotations.of(-0.012939453125);
|
||||
private static final int kFrontRightDriveMotorId = 11;
|
||||
private static final int kFrontRightSteerMotorId = 12;
|
||||
private static final int kFrontRightEncoderId = 13;
|
||||
private static final Angle kFrontRightEncoderOffset = Rotations.of(-0.16162109375);
|
||||
private static final boolean kFrontRightSteerMotorInverted = false;
|
||||
private static final boolean kFrontRightEncoderInverted = false;
|
||||
|
||||
@@ -158,10 +156,10 @@ public class TunerConstants {
|
||||
private static final Distance kFrontRightYPos = Inches.of(-11.375);
|
||||
|
||||
// Back Left
|
||||
private static final int kBackLeftDriveMotorId = 1;
|
||||
private static final int kBackLeftSteerMotorId = 2;
|
||||
private static final int kBackLeftEncoderId = 3;
|
||||
private static final Angle kBackLeftEncoderOffset = Rotations.of(0.07275390625);
|
||||
private static final int kBackLeftDriveMotorId = 21;
|
||||
private static final int kBackLeftSteerMotorId = 22;
|
||||
private static final int kBackLeftEncoderId = 23;
|
||||
private static final Angle kBackLeftEncoderOffset = Rotations.of(-0.017822265625);
|
||||
private static final boolean kBackLeftSteerMotorInverted = false;
|
||||
private static final boolean kBackLeftEncoderInverted = false;
|
||||
|
||||
@@ -172,7 +170,7 @@ public class TunerConstants {
|
||||
private static final int kBackRightDriveMotorId = 31;
|
||||
private static final int kBackRightSteerMotorId = 32;
|
||||
private static final int kBackRightEncoderId = 33;
|
||||
private static final Angle kBackRightEncoderOffset = Rotations.of(-0.4892578125);
|
||||
private static final Angle kBackRightEncoderOffset = Rotations.of(-0.490234375);
|
||||
private static final boolean kBackRightSteerMotorInverted = false;
|
||||
private static final boolean kBackRightEncoderInverted = false;
|
||||
|
||||
@@ -203,7 +201,7 @@ public class TunerConstants {
|
||||
|
||||
/**
|
||||
* Creates a CommandSwerveDrivetrain instance.
|
||||
* This should only be called once in your robot program,.
|
||||
* This should only be called once in your robot program.
|
||||
*/
|
||||
public static CommandSwerveDrivetrain createDrivetrain() {
|
||||
return new CommandSwerveDrivetrain(
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
package frc.robot.utils;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableInstance;
|
||||
import edu.wpi.first.wpilibj.DriverStation;
|
||||
import edu.wpi.first.wpilibj.DriverStation.Alliance;
|
||||
|
||||
public class GameData2026 {
|
||||
private static final double SHIFT_1_END_TIME = 105.0;
|
||||
private static final double SHIFT_2_END_TIME = 80.0;
|
||||
private static final double SHIFT_3_END_TIME = 55.0;
|
||||
private static final double SHIFT_4_END_TIME = 30.0;
|
||||
private static final double TRANSITION_END_TIME = 130.0;
|
||||
|
||||
private final NetworkTable table = NetworkTableInstance.getDefault().getTable("GameData2026");
|
||||
|
||||
public void periodic() {
|
||||
Optional<Alliance> alliance = DriverStation.getAlliance();
|
||||
double matchTime = DriverStation.getMatchTime();
|
||||
String gameData = DriverStation.getGameSpecificMessage();
|
||||
|
||||
HubWindow window = calculateHubWindow(alliance, matchTime, gameData);
|
||||
|
||||
table.getEntry("HubActive").setBoolean(window.hubActive);
|
||||
table.getEntry("HubStatus").setString(window.status);
|
||||
table.getEntry("SecondsUntilHubOpens").setDouble(window.secondsUntilHubOpens);
|
||||
table.getEntry("SecondsUntilHubChanges").setDouble(window.secondsUntilHubChanges);
|
||||
table.getEntry("Shift").setString(window.shift);
|
||||
table.getEntry("MatchTime").setDouble(matchTime);
|
||||
table.getEntry("GameData").setString(gameData);
|
||||
table.getEntry("Alliance").setString(alliance.map(Enum::name).orElse("Unknown"));
|
||||
table.getEntry("FirstInactiveAlliance").setString(getFirstInactiveAlliance(gameData));
|
||||
}
|
||||
|
||||
private HubWindow calculateHubWindow(Optional<Alliance> alliance, double matchTime, String gameData) {
|
||||
if (alliance.isEmpty()) {
|
||||
return new HubWindow(false, "NO_ALLIANCE", "Disabled", Double.NaN, Double.NaN);
|
||||
}
|
||||
|
||||
if (DriverStation.isAutonomousEnabled()) {
|
||||
return new HubWindow(true, "OPEN", "Auto", 0.0, Double.NaN);
|
||||
}
|
||||
|
||||
if (!DriverStation.isTeleopEnabled()) {
|
||||
return new HubWindow(false, "DISABLED", "Disabled", Double.NaN, Double.NaN);
|
||||
}
|
||||
|
||||
if (matchTime < 0.0) {
|
||||
return new HubWindow(true, "OPEN_TIME_UNKNOWN", "Unknown", 0.0, Double.NaN);
|
||||
}
|
||||
|
||||
Boolean redInactiveFirst = getRedInactiveFirst(gameData);
|
||||
if (redInactiveFirst == null) {
|
||||
return new HubWindow(true, "WAITING_DATA", "WaitingData", 0.0, Double.NaN);
|
||||
}
|
||||
|
||||
boolean shift1Active = switch (alliance.get()) {
|
||||
case Red -> !redInactiveFirst;
|
||||
case Blue -> redInactiveFirst;
|
||||
};
|
||||
|
||||
if (matchTime > TRANSITION_END_TIME) {
|
||||
return new HubWindow(true, "OPEN", "Transition", 0.0, matchTime - TRANSITION_END_TIME);
|
||||
} else if (matchTime > SHIFT_1_END_TIME) {
|
||||
return fromShift("Shift1", shift1Active, matchTime, SHIFT_1_END_TIME);
|
||||
} else if (matchTime > SHIFT_2_END_TIME) {
|
||||
return fromShift("Shift2", !shift1Active, matchTime, SHIFT_2_END_TIME);
|
||||
} else if (matchTime > SHIFT_3_END_TIME) {
|
||||
return fromShift("Shift3", shift1Active, matchTime, SHIFT_3_END_TIME);
|
||||
} else if (matchTime > SHIFT_4_END_TIME) {
|
||||
return fromShift("Shift4", !shift1Active, matchTime, SHIFT_4_END_TIME);
|
||||
} else {
|
||||
return new HubWindow(true, "OPEN", "Endgame", 0.0, Math.max(matchTime, 0.0));
|
||||
}
|
||||
}
|
||||
|
||||
private HubWindow fromShift(String shift, boolean hubActive, double matchTime, double nextBoundary) {
|
||||
double secondsUntilChange = Math.max(matchTime - nextBoundary, 0.0);
|
||||
double secondsUntilOpen = hubActive ? 0.0 : secondsUntilChange;
|
||||
String status = hubActive ? "OPEN" : "CLOSED";
|
||||
return new HubWindow(hubActive, status, shift, secondsUntilOpen, secondsUntilChange);
|
||||
}
|
||||
|
||||
private Boolean getRedInactiveFirst(String gameData) {
|
||||
if (gameData.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return switch (gameData.charAt(0)) {
|
||||
case 'R' -> true;
|
||||
case 'B' -> false;
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
private String getFirstInactiveAlliance(String gameData) {
|
||||
if (gameData.isEmpty()) {
|
||||
return "None";
|
||||
}
|
||||
|
||||
return switch (gameData.charAt(0)) {
|
||||
case 'R' -> "Red";
|
||||
case 'B' -> "Blue";
|
||||
default -> "Invalid";
|
||||
};
|
||||
}
|
||||
|
||||
private record HubWindow(
|
||||
boolean hubActive,
|
||||
String status,
|
||||
String shift,
|
||||
double secondsUntilHubOpens,
|
||||
double secondsUntilHubChanges
|
||||
) {}
|
||||
}
|
||||
Reference in New Issue
Block a user