From ed7d0907b189f1b732408164152aca99f1ca5b81 Mon Sep 17 00:00:00 2001 From: Shikhar Date: Tue, 17 Mar 2026 00:31:53 -0600 Subject: [PATCH 1/2] TImer timers for hubshift depending on if u win or lose auto dread --- src/main/java/frc4388/robot/Robot.java | 9 + .../robot/constants/BuildConstants.java | 12 +- .../robot/subsystems/shooter/Shooter.java | 3 + .../utility/compute/HubShiftTimer.java | 154 ++++++++++++++++++ 4 files changed, 172 insertions(+), 6 deletions(-) create mode 100644 src/main/java/frc4388/utility/compute/HubShiftTimer.java diff --git a/src/main/java/frc4388/robot/Robot.java b/src/main/java/frc4388/robot/Robot.java index de52ec1..1b78419 100644 --- a/src/main/java/frc4388/robot/Robot.java +++ b/src/main/java/frc4388/robot/Robot.java @@ -20,6 +20,8 @@ import edu.wpi.first.wpilibj2.command.CommandScheduler; import frc4388.robot.constants.BuildConstants; import frc4388.robot.constants.Constants.SimConstants; import frc4388.utility.DeferredBlock; +import frc4388.utility.compute.HubShiftTimer; +import frc4388.utility.compute.HubShiftTimer.ShiftInfo; import frc4388.utility.compute.RobotTime; import frc4388.utility.compute.Trim; import frc4388.utility.status.FaultReporter; @@ -74,6 +76,11 @@ public class Robot extends LoggedRobot { // and running subsystem periodic() methods. This must be called from the robot's periodic // block in order for anything in the Command-based framework to work. CommandScheduler.getInstance().run(); + //Hub Shift logs + ShiftInfo info = HubShiftTimer.getShiftInfo(); + Logger.recordOutput("HubShift/IsActive", info.isActive()); + Logger.recordOutput("HubShift/RemainingInShift", info.remainingInShift()); + Logger.recordOutput("HubShift/Phase", info.phase().name()); } /** * This function is called once each time the robot enters Disabled mode. @@ -113,6 +120,7 @@ public class Robot extends LoggedRobot { m_autonomousCommand.schedule(); } m_robotTime.startMatchTime(); + HubShiftTimer.initializeAuto(); } /** @@ -138,6 +146,7 @@ public class Robot extends LoggedRobot { } m_robotTime.startMatchTime(); + HubShiftTimer.initializeTeleop(); } /** diff --git a/src/main/java/frc4388/robot/constants/BuildConstants.java b/src/main/java/frc4388/robot/constants/BuildConstants.java index 9ff0c32..92740de 100644 --- a/src/main/java/frc4388/robot/constants/BuildConstants.java +++ b/src/main/java/frc4388/robot/constants/BuildConstants.java @@ -7,12 +7,12 @@ public final class BuildConstants { public static final String MAVEN_GROUP = ""; public static final String MAVEN_NAME = "2026KPopRobotHunters"; public static final String VERSION = "unspecified"; - public static final int GIT_REVISION = 147; - public static final String GIT_SHA = "b073fad27703951ba251eaffc56d86f791e531e6"; - public static final String GIT_DATE = "2026-03-07 20:08:15 MST"; - public static final String GIT_BRANCH = "PikesPeak"; - public static final String BUILD_DATE = "2026-03-08 14:27:19 MDT"; - public static final long BUILD_UNIX_TIME = 1773001639109L; + public static final int GIT_REVISION = 148; + public static final String GIT_SHA = "5b85bb4ace55dd116c3e80c496ad3ebf986ebfc8"; + public static final String GIT_DATE = "2026-03-09 10:27:13 MDT"; + public static final String GIT_BRANCH = "Timer"; + public static final String BUILD_DATE = "2026-03-17 00:27:11 MDT"; + public static final long BUILD_UNIX_TIME = 1773728831770L; public static final int DIRTY = 1; private BuildConstants(){} diff --git a/src/main/java/frc4388/robot/subsystems/shooter/Shooter.java b/src/main/java/frc4388/robot/subsystems/shooter/Shooter.java index 15f0edf..5a8f84d 100644 --- a/src/main/java/frc4388/robot/subsystems/shooter/Shooter.java +++ b/src/main/java/frc4388/robot/subsystems/shooter/Shooter.java @@ -19,6 +19,8 @@ import frc4388.robot.subsystems.LED; import frc4388.robot.subsystems.intake.Intake; import frc4388.robot.subsystems.swerve.SwerveDrive; import frc4388.utility.compute.FieldPositions; +import frc4388.utility.compute.HubShiftTimer; +import frc4388.utility.compute.HubShiftTimer.ShiftInfo; public class Shooter extends SubsystemBase { public ShooterIO io; @@ -104,6 +106,7 @@ public class Shooter extends SubsystemBase { // FaultReporter.register(this); // TODO Implement fault reporter Logger.processInputs("Shooter", state); + io.updateInputs(state); diff --git a/src/main/java/frc4388/utility/compute/HubShiftTimer.java b/src/main/java/frc4388/utility/compute/HubShiftTimer.java new file mode 100644 index 0000000..6f91284 --- /dev/null +++ b/src/main/java/frc4388/utility/compute/HubShiftTimer.java @@ -0,0 +1,154 @@ + +package frc4388.utility.compute; +import edu.wpi.first.wpilibj.DriverStation; +import edu.wpi.first.wpilibj.DriverStation.Alliance; +import edu.wpi.first.wpilibj.Timer; +public class HubShiftTimer { + + public enum ShiftPhase { + DISABLED, + AUTO, + TRANSITION, // 0 – 10 s + SHIFT1, // 10 – 35 s + SHIFT2, // 35 – 60 s + SHIFT3, // 60 – 85 s + SHIFT4, // 85 – 110 s + ENDGAME // 110 – 140 s + } + + public record ShiftInfo( + ShiftPhase phase, + double elapsedInShift, + double remainingInShift, + boolean isActive) {} +//total teleop time + public static final double TELEOP_DURATION = 140.0; +//total auto time + public static final double AUTO_DURATION = 20.0; + +//shift start and end times for calculations + private static final double[] SHIFT_STARTS = {0.0, 10.0, 35.0, 60.0, 85.0, 110.0}; + private static final double[] SHIFT_ENDS = {10.0, 35.0, 60.0, 85.0, 110.0, 140.0}; + +//hub active schedule, true is active and false is inactive +//starts always as active becasue transition is first and is active, but then is inactive for winner or active for loser + private static final boolean[] WINNER_SCHEDULE = {true, false, true, false, true, true}; + private static final boolean[] LOSER_SCHEDULE = {true, true, false, true, false, true}; + +//shift phase names during teleop + private static final ShiftPhase[] SHIFT_PHASES = { + ShiftPhase.TRANSITION, + ShiftPhase.SHIFT1, + ShiftPhase.SHIFT2, + ShiftPhase.SHIFT3, + ShiftPhase.SHIFT4, + ShiftPhase.ENDGAME + }; + +//timer to track time + private static final Timer teleopTimer = new Timer(); + private static double timerOffset = 0.0; + +//fms syncing idk other team did it too + private static final double RESYNC_THRESHOLD = 3.0; + + +//call at start of auto to start timer + public static void initializeAuto() { + teleopTimer.restart(); + } + +//call at start of teleop to start timer again because sometimes delay between auto and telop + public static void initializeTeleop() { + timerOffset = 0.0; + teleopTimer.restart(); + } + + + +//returns the updated shift info based on the winner of auto + public static ShiftInfo getShiftInfo() { + if (!DriverStation.isEnabled()) { + return new ShiftInfo(ShiftPhase.DISABLED, 0.0, 0.0, false); + } + if (DriverStation.isAutonomousEnabled()) { + double autoElapsed = teleopTimer.get(); // timer restarts in initialize() + return new ShiftInfo( + ShiftPhase.AUTO, + autoElapsed, + Math.max(0.0, AUTO_DURATION - teleopTimer.get()), + true); + } + return computeTeleopShift(); + } + +//find auto winner, R = red wins, B = blue wins + public static Alliance autoWinnerAlliance() { + String msg = DriverStation.getGameSpecificMessage(); + if (msg != null && msg.length() > 0) { + char c = msg.charAt(0); + if (c == 'R') return Alliance.Red; + if (c == 'B') return Alliance.Blue; + } + // backup if no msg, returns auto winner as opposite of our alliance. if we red -> blue wins auto + Alliance ours = DriverStation.getAlliance().orElse(Alliance.Blue); + return (ours == Alliance.Blue) ? Alliance.Red : Alliance.Blue; + } + + + //return our schedule for the shifts + private static boolean[] getSchedule() { + Alliance ours = DriverStation.getAlliance().orElse(Alliance.Blue); + Alliance winner = autoWinnerAlliance(); + return (ours == winner) ? WINNER_SCHEDULE : LOSER_SCHEDULE; + } + +//time since start of teleop + private static double getTeleopElapsed() { + double localTime = teleopTimer.get() - timerOffset; + + // Re-sync to FMS time if we drift too far (only when FMS is attached) + if (DriverStation.isFMSAttached()) { + double fmsElapsed = TELEOP_DURATION - DriverStation.getMatchTime(); + if (fmsElapsed <= TELEOP_DURATION - 5.0 // ignore the first few seconds of jitter + && Math.abs(localTime - fmsElapsed) >= RESYNC_THRESHOLD) { + timerOffset += localTime - fmsElapsed; + localTime = fmsElapsed; + } + } + return Math.max(0.0, Math.min(TELEOP_DURATION, localTime)); + } + + private static ShiftInfo computeTeleopShift() { + boolean[] schedule = getSchedule(); + double elapsed = getTeleopElapsed(); + + // Find which shift we're in + int phaseIndex = SHIFT_STARTS.length - 1; // default to last shift if past all bounds + for (int i = 0; i < SHIFT_STARTS.length; i++) { + if (elapsed >= SHIFT_STARTS[i] && elapsed < SHIFT_ENDS[i]) { + phaseIndex = i; + break; + } + } + + double shiftElapsed = elapsed - SHIFT_STARTS[phaseIndex]; + double shiftRemaining = SHIFT_ENDS[phaseIndex] - elapsed; + + // merge time for elapsed if same active/inactive + if (phaseIndex > 0 && schedule[phaseIndex] == schedule[phaseIndex - 1]) { + shiftElapsed = elapsed - SHIFT_STARTS[phaseIndex - 1]; + } + + // merge time for remaining time if same active/inactive status + if (phaseIndex < SHIFT_ENDS.length - 1 && schedule[phaseIndex] == schedule[phaseIndex + 1]) { + shiftRemaining = SHIFT_ENDS[phaseIndex + 1] - elapsed; + } + + return new ShiftInfo( + SHIFT_PHASES[phaseIndex], + shiftElapsed, + shiftRemaining, + schedule[phaseIndex]); + } +} \ No newline at end of file From 03d95a273de6aed5161050e3939fd8de52103543 Mon Sep 17 00:00:00 2001 From: Shikhar Date: Wed, 18 Mar 2026 12:02:24 -0600 Subject: [PATCH 2/2] Fix to robot java --- simgui-ds.json | 5 ----- src/main/java/frc4388/robot/Robot.java | 5 ----- .../java/frc4388/robot/constants/BuildConstants.java | 10 +++++----- .../java/frc4388/robot/subsystems/shooter/Shooter.java | 6 +++++- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/simgui-ds.json b/simgui-ds.json index 4a63cc1..73cc713 100644 --- a/simgui-ds.json +++ b/simgui-ds.json @@ -1,9 +1,4 @@ { - "System Joysticks": { - "window": { - "enabled": false - } - }, "keyboardJoysticks": [ { "axisConfig": [ diff --git a/src/main/java/frc4388/robot/Robot.java b/src/main/java/frc4388/robot/Robot.java index 1b78419..c6bf398 100644 --- a/src/main/java/frc4388/robot/Robot.java +++ b/src/main/java/frc4388/robot/Robot.java @@ -76,11 +76,6 @@ public class Robot extends LoggedRobot { // and running subsystem periodic() methods. This must be called from the robot's periodic // block in order for anything in the Command-based framework to work. CommandScheduler.getInstance().run(); - //Hub Shift logs - ShiftInfo info = HubShiftTimer.getShiftInfo(); - Logger.recordOutput("HubShift/IsActive", info.isActive()); - Logger.recordOutput("HubShift/RemainingInShift", info.remainingInShift()); - Logger.recordOutput("HubShift/Phase", info.phase().name()); } /** * This function is called once each time the robot enters Disabled mode. diff --git a/src/main/java/frc4388/robot/constants/BuildConstants.java b/src/main/java/frc4388/robot/constants/BuildConstants.java index 92740de..ae43c17 100644 --- a/src/main/java/frc4388/robot/constants/BuildConstants.java +++ b/src/main/java/frc4388/robot/constants/BuildConstants.java @@ -7,12 +7,12 @@ public final class BuildConstants { public static final String MAVEN_GROUP = ""; public static final String MAVEN_NAME = "2026KPopRobotHunters"; public static final String VERSION = "unspecified"; - public static final int GIT_REVISION = 148; - public static final String GIT_SHA = "5b85bb4ace55dd116c3e80c496ad3ebf986ebfc8"; - public static final String GIT_DATE = "2026-03-09 10:27:13 MDT"; + public static final int GIT_REVISION = 149; + public static final String GIT_SHA = "ed7d0907b189f1b732408164152aca99f1ca5b81"; + public static final String GIT_DATE = "2026-03-17 00:31:53 MDT"; public static final String GIT_BRANCH = "Timer"; - public static final String BUILD_DATE = "2026-03-17 00:27:11 MDT"; - public static final long BUILD_UNIX_TIME = 1773728831770L; + public static final String BUILD_DATE = "2026-03-17 12:46:28 MDT"; + public static final long BUILD_UNIX_TIME = 1773773188939L; public static final int DIRTY = 1; private BuildConstants(){} diff --git a/src/main/java/frc4388/robot/subsystems/shooter/Shooter.java b/src/main/java/frc4388/robot/subsystems/shooter/Shooter.java index 5a8f84d..75e6225 100644 --- a/src/main/java/frc4388/robot/subsystems/shooter/Shooter.java +++ b/src/main/java/frc4388/robot/subsystems/shooter/Shooter.java @@ -104,7 +104,11 @@ public class Shooter extends SubsystemBase { @Override public void periodic() { // FaultReporter.register(this); // TODO Implement fault reporter - + //Hub Shift logs + ShiftInfo info = HubShiftTimer.getShiftInfo(); + Logger.recordOutput("HubShift/IsActive", info.isActive()); + Logger.recordOutput("HubShift/RemainingInShift", info.remainingInShift()); + Logger.recordOutput("HubShift/Phase", info.phase().name()); Logger.processInputs("Shooter", state); io.updateInputs(state);