计时器

This commit is contained in:
OnDYCLaptop
2026-06-16 12:12:24 +08:00
parent af1095cf50
commit 99a92af429
4 changed files with 212 additions and 1 deletions
+88 -1
View File
@@ -91,6 +91,93 @@
"period": 0.06, "period": 0.06,
"sort_options": false "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
}
} }
] ]
} }
@@ -1492,4 +1579,4 @@
} }
} }
] ]
} }
+1
View File
@@ -23,6 +23,7 @@ public class Robot extends TimedRobot {
public void robotPeriodic() { public void robotPeriodic() {
CommandScheduler.getInstance().run(); CommandScheduler.getInstance().run();
m_robotContainer.tunerPeriodic(); m_robotContainer.tunerPeriodic();
m_robotContainer.dashboardPeriodic();
} }
@@ -30,6 +30,7 @@ import frc.robot.utils.LedBindings;
import frc.robot.controls.ClimberControls; import frc.robot.controls.ClimberControls;
import frc.robot.controls.Autocommand; import frc.robot.controls.Autocommand;
import frc.robot.subsystems.ClimberSubsystem; import frc.robot.subsystems.ClimberSubsystem;
import frc.robot.utils.GameData2026;
public class RobotContainer { public class RobotContainer {
/* ====================== */ /* ====================== */
@@ -63,6 +64,7 @@ public class RobotContainer {
//private final ClimberControls climberControls = new ClimberControls(climberSubsystem, controllerupper); //private final ClimberControls climberControls = new ClimberControls(climberSubsystem, controllerupper);
private final IntakerControls intakerControls = new IntakerControls(IntakerSubsystem, shooterSubsystem, controllerupper); private final IntakerControls intakerControls = new IntakerControls(IntakerSubsystem, shooterSubsystem, controllerupper);
private final DriveGainsTuner driveGainsTuner = new DriveGainsTuner(drivetrain); 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 configFlywheelTuner = new ConfigTalonFXMotorTuner(shooterSubsystem.flywheelMotorLeft, "flywheel", Constants.Shooter.flyWheelSlot0Configs);
private ConfigTalonFXMotorTuner configConveyorTuner = new ConfigTalonFXMotorTuner(shooterSubsystem.conveyorMotor, "conveyor", Constants.Shooter.conveyorSlot0Configs); private ConfigTalonFXMotorTuner configConveyorTuner = new ConfigTalonFXMotorTuner(shooterSubsystem.conveyorMotor, "conveyor", Constants.Shooter.conveyorSlot0Configs);
private ConfigTalonFXSMotorTuner configBackboardTuner = new ConfigTalonFXSMotorTuner(shooterSubsystem.backboardMotor, "backboard", Constants.Shooter.backboardSlot0Configs); private ConfigTalonFXSMotorTuner configBackboardTuner = new ConfigTalonFXSMotorTuner(shooterSubsystem.backboardMotor, "backboard", Constants.Shooter.backboardSlot0Configs);
@@ -202,6 +204,10 @@ public class RobotContainer {
shooterSubsystem.setRightFollowLeft(); shooterSubsystem.setRightFollowLeft();
} }
public void dashboardPeriodic() {
gameData2026.periodic();
}
// private void configueClimber() { // private void configueClimber() {
// climberSubsystem.setDefaultCommand(climberControls.defaultClimberCommand()); // climberSubsystem.setDefaultCommand(climberControls.defaultClimberCommand());
// } // }
@@ -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
) {}
}