From 467966dacd77a6e2bc0615f4ace30748a9c67627 Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Sun, 18 Jan 2026 13:42:53 -0500 Subject: [PATCH 01/21] Added code from last year for the autochooser (broken). --- src/main/java/frc/robot/Robot.java | 6 +- src/main/java/frc/robot/RobotContainer.java | 7 + .../frc/robot/autochooser/AutoAction.java | 37 ++++++ .../frc/robot/autochooser/FieldLocation.java | 59 +++++++++ .../autochooser/chooser/AutoChooser.java | 16 +++ .../autochooser/chooser/AutoChooser2025.java | 59 +++++++++ .../autochooser/event/AutoChooserInputs.java | 39 ++++++ .../robot/autochooser/event/AutoEvent.java | 40 ++++++ .../autochooser/event/AutoEventProvider.java | 76 +++++++++++ .../event/AutoEventProviderIO.java | 24 ++++ .../event/RealAutoEventProvider.java | 121 ++++++++++++++++++ 11 files changed, 483 insertions(+), 1 deletion(-) create mode 100644 src/main/java/frc/robot/autochooser/AutoAction.java create mode 100644 src/main/java/frc/robot/autochooser/FieldLocation.java create mode 100644 src/main/java/frc/robot/autochooser/chooser/AutoChooser.java create mode 100644 src/main/java/frc/robot/autochooser/chooser/AutoChooser2025.java create mode 100644 src/main/java/frc/robot/autochooser/event/AutoChooserInputs.java create mode 100644 src/main/java/frc/robot/autochooser/event/AutoEvent.java create mode 100644 src/main/java/frc/robot/autochooser/event/AutoEventProvider.java create mode 100644 src/main/java/frc/robot/autochooser/event/AutoEventProviderIO.java create mode 100644 src/main/java/frc/robot/autochooser/event/RealAutoEventProvider.java diff --git a/src/main/java/frc/robot/Robot.java b/src/main/java/frc/robot/Robot.java index 6aec93a..378df19 100644 --- a/src/main/java/frc/robot/Robot.java +++ b/src/main/java/frc/robot/Robot.java @@ -113,7 +113,7 @@ public void robotPeriodic() { if (DriverStation.isDSAttached() && allianceColor.isEmpty()) { allianceColor = DriverStation.getAlliance(); if (allianceColor.isPresent()) { - // robotContainer.getAutoChooser().getProvider().forceRefresh(); + robotContainer.getAutoChooser().getProvider().forceRefresh(); } } } @@ -211,5 +211,9 @@ public void simulationInit() {} @Override public void simulationPeriodic() {} + // getters + /** @return whether the hub is active */ public static boolean hubActive() {return hubActive;} + /** @return the alliance color */ + public static Optional getAllianceColor() {return allianceColor;} } diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index f664f73..5c7aa6d 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -8,6 +8,7 @@ import edu.wpi.first.wpilibj2.command.Command; import edu.wpi.first.wpilibj2.command.button.CommandXboxController; import edu.wpi.first.wpilibj2.command.button.Trigger; +import frc.robot.autochooser.chooser.AutoChooser2025; import frc.robot.commands.roller.SpinRoller; import frc.robot.commands.tilt.TiltDown; import frc.robot.commands.tilt.TiltUp; @@ -26,6 +27,7 @@ public class RobotContainer { private final RollerSubsystem rollerSubsystem; private final TiltSubsystem tiltSubsystem; private RobotVisualizer robotVisualizer = null; + private final AutoChooser2025 autoChooser; // Replace with CommandPS4Controller or CommandJoystick if needed //new CommandXboxController(OperatorConstants.kDriverControllerPort); @@ -52,6 +54,7 @@ public RobotContainer() { } configureBindings(); putShuffleboardCommands(); + autoChooser = new AutoChooser2025(null); } /** @@ -99,4 +102,8 @@ public Command getAutonomousCommand() { public RobotVisualizer getRobotVisualizer() { return robotVisualizer; } + + public Object getAutoChooser() { + return autoChooser; + } } diff --git a/src/main/java/frc/robot/autochooser/AutoAction.java b/src/main/java/frc/robot/autochooser/AutoAction.java new file mode 100644 index 0000000..cbb8da9 --- /dev/null +++ b/src/main/java/frc/robot/autochooser/AutoAction.java @@ -0,0 +1,37 @@ +package frc.robot.autochooser; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.function.Function; +import java.util.stream.Collectors; + +public enum AutoAction { + DO_NOTHING("Do Nothing"), + TWO_PIECE_HIGH("2 Piece L4"), + TWO_PIECE_LOW("2 Piece L2"), + ONE_PIECE("1 Piece"), + CROSS_THE_LINE("Cross The Line"), + INVALID("INVALID"); + private final String name; + private static final HashMap nameMap = + new HashMap<>( + Arrays.stream(AutoAction.values()) + .collect(Collectors.toMap(AutoAction::getName, Function.identity()))); + + AutoAction(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return getName(); + } + + public static AutoAction fromName(String name) { + return nameMap.get(name); + } +} diff --git a/src/main/java/frc/robot/autochooser/FieldLocation.java b/src/main/java/frc/robot/autochooser/FieldLocation.java new file mode 100644 index 0000000..bb8ae60 --- /dev/null +++ b/src/main/java/frc/robot/autochooser/FieldLocation.java @@ -0,0 +1,59 @@ +package frc.robot.autochooser; + +import static edu.wpi.first.wpilibj.DriverStation.Alliance; + +import edu.wpi.first.math.geometry.Pose2d; +import edu.wpi.first.math.geometry.Rotation2d; +import edu.wpi.first.math.util.Units; +import frc.robot.Robot; +import java.util.Arrays; +import java.util.HashMap; +import java.util.function.Function; +import java.util.stream.Collectors; + +public enum FieldLocation { + ZERO(0, 0, 0, "Zero"), + INVALID(-1, -1, -1, "INVALID"), + LEFT(7.150, 7.000, 180, "NON Processor Side"), + MIDDLE(7.150, 4.500, 180, "Middle"), + RIGHT(7.150, 2.000, 180, "Processor Side"); + + private static final double RED_X_POS = 2.3876; // meters + public static final double HEIGHT_OF_FIELD = 8.05; + public static final double LENGTH_OF_FIELD = 17.548225; + private final double yPose; + private final double xPose; + private final double angle; + private final String name; + private static final HashMap nameMap = + new HashMap<>( + Arrays.stream(FieldLocation.values()) + .collect(Collectors.toMap(FieldLocation::getShuffleboardName, Function.identity()))); + + FieldLocation(double xPos, double yPose, double angle, String name) { + this.xPose = xPos; + this.yPose = yPose; + this.angle = angle; + this.name = name; + } + + public static FieldLocation fromName(String string) { + return nameMap.get(string); + } + + public Pose2d getLocation() { + Alliance alliance = Robot.getAllianceColor().orElse(null); + if (alliance == null) { + return new Pose2d(INVALID.xPose, INVALID.yPose, Rotation2d.fromDegrees(INVALID.angle)); + } + double x = (alliance == Alliance.Red) ? xPose + RED_X_POS + Units.inchesToMeters(36) : xPose; + double y = (alliance == Alliance.Red) ? yPose - 2 * (yPose - (HEIGHT_OF_FIELD / 2)) : yPose; + double radian = + (alliance == Alliance.Red) ? Math.toRadians(180 - angle) : Math.toRadians(angle); + return new Pose2d(x, y, Rotation2d.fromRadians(radian)); + } + + public String getShuffleboardName() { + return name; + } +} diff --git a/src/main/java/frc/robot/autochooser/chooser/AutoChooser.java b/src/main/java/frc/robot/autochooser/chooser/AutoChooser.java new file mode 100644 index 0000000..f2edea8 --- /dev/null +++ b/src/main/java/frc/robot/autochooser/chooser/AutoChooser.java @@ -0,0 +1,16 @@ +package frc.robot.autochooser.chooser; + +import edu.wpi.first.math.geometry.Pose2d; +import edu.wpi.first.wpilibj2.command.Command; +import frc.robot.autochooser.event.AutoEvent; + +/** interface for taking in a {@link AutoEvent} and returning the corresponding {@link Command} */ +public interface AutoChooser { + /** + * @return Command that corresponds to the selected {@link AutoEvent} from the {@link + * frc.robot.autochooser.event.AutoEventProvider} + */ + Command getAutoCommand(); + + Pose2d getStartingPosition(); +} diff --git a/src/main/java/frc/robot/autochooser/chooser/AutoChooser2025.java b/src/main/java/frc/robot/autochooser/chooser/AutoChooser2025.java new file mode 100644 index 0000000..a5df7a3 --- /dev/null +++ b/src/main/java/frc/robot/autochooser/chooser/AutoChooser2025.java @@ -0,0 +1,59 @@ +package frc.robot.autochooser.chooser; + +import edu.wpi.first.math.geometry.Pose2d; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.SubsystemBase; +import frc.robot.autochooser.AutoAction; +import frc.robot.autochooser.FieldLocation; +import frc.robot.autochooser.event.AutoEvent; +import frc.robot.autochooser.event.AutoEventProvider; +import frc.robot.autochooser.event.AutoEventProviderIO; +import frc.robot.utils.logging.commands.DoNothingCommand; +import java.util.Map; + +public class AutoChooser2025 extends SubsystemBase implements AutoChooser { + private final Map commandMap; + private final AutoEventProvider provider; + // private final SwerveDrivetrain drivetrain; + + public AutoChooser2025( + AutoEventProviderIO providerIO + // SwerveDrivetrain drivetrain, + ) { + provider = new AutoEventProvider(providerIO, this::isValid); + // this.drivetrain = drivetrain; + commandMap = + Map.ofEntries( + Map.entry( + new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.LEFT), new DoNothingCommand()), + Map.entry( + new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.MIDDLE), new DoNothingCommand()), + Map.entry( + new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.RIGHT), new DoNothingCommand()) + ); + } + + @Override + public Command getAutoCommand() { + return commandMap.get( + new AutoEvent(provider.getSelectedAction(), provider.getSelectedLocation())); + } + + @Override + public Pose2d getStartingPosition() { + return provider.getSelectedLocation().getLocation(); + } + + protected boolean isValid(AutoAction action, FieldLocation location) { + return commandMap.containsKey(new AutoEvent(action, location)); + } + + @Override + public void periodic() { + provider.updateInputs(); + } + + public AutoEventProvider getProvider() { + return provider; + } +} diff --git a/src/main/java/frc/robot/autochooser/event/AutoChooserInputs.java b/src/main/java/frc/robot/autochooser/event/AutoChooserInputs.java new file mode 100644 index 0000000..f307cec --- /dev/null +++ b/src/main/java/frc/robot/autochooser/event/AutoChooserInputs.java @@ -0,0 +1,39 @@ +package frc.robot.autochooser.event; + +import frc.robot.autochooser.AutoAction; +import frc.robot.autochooser.FieldLocation; +import frc.robot.utils.logging.subsystem.FolderLoggableInputs; +import org.littletonrobotics.junction.LogTable; + +public class AutoChooserInputs extends FolderLoggableInputs { + AutoAction action = AutoAction.INVALID; + FieldLocation location = FieldLocation.INVALID; + AutoAction defaultAction = AutoAction.INVALID; + FieldLocation defaultLocation = FieldLocation.INVALID; + AutoAction feedbackAction = AutoAction.INVALID; + FieldLocation feedbackLocation = FieldLocation.INVALID; + + public AutoChooserInputs(String folder) { + super(folder); + } + + @Override + public void toLog(LogTable table) { + table.put("action", action); + table.put("location", location); + table.put("defaultAction", defaultAction); + table.put("defaultLocation", defaultLocation); + table.put("feedbackAction", feedbackAction); + table.put("feedbackLocation", feedbackLocation); + } + + @Override + public void fromLog(LogTable table) { + action = table.get("action", action); + location = table.get("location", location); + defaultAction = table.get("defaultAction", defaultAction); + defaultLocation = table.get("defaultLocation", defaultLocation); + feedbackAction = table.get("feedbackAction", feedbackAction); + feedbackLocation = table.get("feedbackLocation", feedbackLocation); + } +} diff --git a/src/main/java/frc/robot/autochooser/event/AutoEvent.java b/src/main/java/frc/robot/autochooser/event/AutoEvent.java new file mode 100644 index 0000000..977f323 --- /dev/null +++ b/src/main/java/frc/robot/autochooser/event/AutoEvent.java @@ -0,0 +1,40 @@ +package frc.robot.autochooser.event; + +import frc.robot.autochooser.AutoAction; +import frc.robot.autochooser.FieldLocation; +import java.util.Objects; + +/** + * Wrapper Class, that Contains a {@link frc.robot.autochooser.AutoAction} and a {@link + * frc.robot.autochooser.FieldLocation} + */ +public class AutoEvent { + private final AutoAction action; + private final FieldLocation location; + + public AutoEvent(AutoAction action, FieldLocation location) { + this.action = action; + this.location = location; + } + + public AutoAction getAction() { + return action; + } + + public FieldLocation getLocation() { + return location; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AutoEvent autoEvent = (AutoEvent) o; + return action.equals(autoEvent.action) && location.equals(autoEvent.location); + } + + @Override + public int hashCode() { + return Objects.hash(action, location); + } +} diff --git a/src/main/java/frc/robot/autochooser/event/AutoEventProvider.java b/src/main/java/frc/robot/autochooser/event/AutoEventProvider.java new file mode 100644 index 0000000..277ac89 --- /dev/null +++ b/src/main/java/frc/robot/autochooser/event/AutoEventProvider.java @@ -0,0 +1,76 @@ +package frc.robot.autochooser.event; + +import frc.robot.Robot; +import frc.robot.autochooser.AutoAction; +import frc.robot.autochooser.FieldLocation; +import frc.robot.utils.logging.subsystem.LoggableSystem; +import java.util.function.BiFunction; +import java.util.function.Consumer; + +/** + * Superclass of {@link AutoEventProviderIO} that uses Network Tables to get {@link AutoAction + * AutoActions} and {@link FieldLocation fieldLocations}
+ */ +public class AutoEventProvider { + private final LoggableSystem system; + private final BiFunction validator; + private boolean changed = false; + + public AutoEventProvider( + AutoEventProviderIO providerIO, BiFunction validator) { + this.system = new LoggableSystem<>(providerIO, new AutoChooserInputs("AutoChooser")); + this.validator = validator; + setOnActionChangeListener((a) -> changed = true); + setOnLocationChangeListener((l) -> changed = true); + } + + public AutoAction getSelectedAction() { + return system.getInputs().action == null + ? system.getInputs().defaultAction + : system.getInputs().action; + } + + public FieldLocation getSelectedLocation() { + return system.getInputs().location == null + ? system.getInputs().defaultLocation + : system.getInputs().location; + } + + public void updateInputs() { + FieldLocation lastsLoc = system.getInputs().location; + AutoAction lastsAct = system.getInputs().action; + system.updateInputs(); + if (!Robot.isReal() + && (!lastsLoc.equals(system.getInputs().location) + || !lastsAct.equals(system.getInputs().action))) { + changed = true; + } + if (changed) { + forceRefresh(); + changed = false; + } + } + + public void setOnActionChangeListener(Consumer listener) { + system.getIO().setOnActionChangeListener(listener); + } + + public void setOnLocationChangeListener(Consumer listener) { + system.getIO().setOnLocationChangeListener(listener); + } + + public void forceRefresh() { + if (validator.apply(getSelectedAction(), getSelectedLocation())) { + system.getIO().setFeedbackAction(getSelectedAction()); + system.getIO().setFeedbackLocation(getSelectedLocation()); + system.getIO().runValidCommands(); + } else { + system.getIO().setFeedbackAction(AutoAction.INVALID); + system.getIO().setFeedbackLocation(FieldLocation.INVALID); + } + } + + public void addOnValidationCommand(Runnable c) { + system.getIO().addOnValidationCommand(c); + } +} diff --git a/src/main/java/frc/robot/autochooser/event/AutoEventProviderIO.java b/src/main/java/frc/robot/autochooser/event/AutoEventProviderIO.java new file mode 100644 index 0000000..26e4b28 --- /dev/null +++ b/src/main/java/frc/robot/autochooser/event/AutoEventProviderIO.java @@ -0,0 +1,24 @@ +package frc.robot.autochooser.event; + +import frc.robot.autochooser.AutoAction; +import frc.robot.autochooser.FieldLocation; +import frc.robot.utils.logging.LoggableIO; +import java.util.function.Consumer; + +/** + * interface that outlines the necessary methods to provide {@link FieldLocation FieldLocations} and + * {@link AutoAction AutoActions} + */ +public interface AutoEventProviderIO extends LoggableIO { + void setOnActionChangeListener(Consumer listener); + + void setOnLocationChangeListener(Consumer listener); + + void addOnValidationCommand(Runnable consumer); + + void runValidCommands(); + + void setFeedbackAction(AutoAction action); + + void setFeedbackLocation(FieldLocation location); +} diff --git a/src/main/java/frc/robot/autochooser/event/RealAutoEventProvider.java b/src/main/java/frc/robot/autochooser/event/RealAutoEventProvider.java new file mode 100644 index 0000000..946a3bb --- /dev/null +++ b/src/main/java/frc/robot/autochooser/event/RealAutoEventProvider.java @@ -0,0 +1,121 @@ +package frc.robot.autochooser.event; + +import edu.wpi.first.networktables.NetworkTableValue; +import edu.wpi.first.wpilibj.shuffleboard.BuiltInWidgets; +import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; +import edu.wpi.first.wpilibj.shuffleboard.ShuffleboardTab; +import edu.wpi.first.wpilibj.smartdashboard.SendableChooser; +import frc.robot.autochooser.AutoAction; +import frc.robot.autochooser.FieldLocation; +import frc.robot.utils.shuffleboard.SmartShuffleboard; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; + +public class RealAutoEventProvider implements AutoEventProviderIO { + + public static final String AUTO_TAB_NAME = "Auto"; + public static final String ACTION_FIELD_NAME = "Auto Action"; + public static final String LOCATION_FIELD_NAME = "Location Chooser"; + public static final String AUTO_LOCATION_FEEDBACK_NAME = "FieldLocationFeedback"; + public static final String AUTO_ACTION_FEEDBACK_NAME = "AutoActionFeedback"; + + private final SendableChooser actionChooser; + private final SendableChooser locationChooser; + private final AutoAction defaultAutoAction; + private final FieldLocation defaultFieldLocation; + public final List onValidEvents = new ArrayList<>(); + + public RealAutoEventProvider(AutoAction defaultAutoAction, FieldLocation defaultFieldLocation) { + this.defaultAutoAction = defaultAutoAction; + this.defaultFieldLocation = defaultFieldLocation; + this.actionChooser = new SendableChooser<>(); + this.locationChooser = new SendableChooser<>(); + Arrays.stream(AutoAction.values()).forEach(a -> actionChooser.addOption(a.getName(), a)); + Arrays.stream(FieldLocation.values()) + .forEach(l -> locationChooser.addOption(l.getShuffleboardName(), l)); + actionChooser.setDefaultOption(defaultAutoAction.getName(), defaultAutoAction); + locationChooser.setDefaultOption( + defaultFieldLocation.getShuffleboardName(), defaultFieldLocation); + ShuffleboardTab autoTab = Shuffleboard.getTab(AUTO_TAB_NAME); + autoTab + .add(ACTION_FIELD_NAME, actionChooser) + .withWidget(BuiltInWidgets.kComboBoxChooser) + .withPosition(0, 0) + .withSize(4, 1); + autoTab.add(LOCATION_FIELD_NAME, locationChooser).withPosition(0, 1).withSize(4, 1); + SmartShuffleboard.put(AUTO_TAB_NAME, AUTO_ACTION_FEEDBACK_NAME, defaultAutoAction.toString()) + .withPosition(2, 2) + .withSize(2, 1); + SmartShuffleboard.put( + AUTO_TAB_NAME, AUTO_LOCATION_FEEDBACK_NAME, defaultFieldLocation.getShuffleboardName()) + .withPosition(0, 2) + .withSize(2, 1); + } + + /** + * @param listener function to be called when the value in {@link #actionChooser} changes + */ + @Override + public void setOnActionChangeListener(Consumer listener) { + actionChooser.onChange(listener); + } + + /** + * @param listener function to be called when the value in {@link #locationChooser} changes + */ + @Override + public void setOnLocationChangeListener(Consumer listener) { + locationChooser.onChange(listener); + } + + @Override + public void addOnValidationCommand(Runnable consumer) { + onValidEvents.add(consumer); + } + + @Override + public void runValidCommands() { + onValidEvents.forEach( + c -> { + try { + c.run(); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + + @Override + public void setFeedbackAction(AutoAction action) { + SmartShuffleboard.put(AUTO_TAB_NAME, AUTO_ACTION_FEEDBACK_NAME, action.toString()); + } + + @Override + public void setFeedbackLocation(FieldLocation location) { + SmartShuffleboard.put( + AUTO_TAB_NAME, AUTO_LOCATION_FEEDBACK_NAME, location.getShuffleboardName()); + } + + @Override + public void updateInputs(AutoChooserInputs inputs) { + inputs.action = actionChooser.getSelected(); + inputs.location = locationChooser.getSelected(); + inputs.defaultAction = defaultAutoAction; + inputs.defaultLocation = defaultFieldLocation; + NetworkTableValue feedbackLocation = + SmartShuffleboard.getValue(AUTO_TAB_NAME, AUTO_LOCATION_FEEDBACK_NAME); + if (feedbackLocation == null || feedbackLocation.getString().isBlank()) { + inputs.feedbackLocation = FieldLocation.INVALID; + } else { + inputs.feedbackLocation = FieldLocation.fromName(feedbackLocation.getString()); + } + NetworkTableValue action = SmartShuffleboard.getValue(AUTO_TAB_NAME, AUTO_ACTION_FEEDBACK_NAME); + if (action == null || action.getString().isBlank()) { + inputs.feedbackAction = AutoAction.INVALID; + } else { + inputs.feedbackAction = AutoAction.fromName(action.toString()); + } + } +} From d2039a93bb0f98962f3f16488518d44e84c96e68 Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Sun, 18 Jan 2026 16:19:37 -0500 Subject: [PATCH 02/21] The autochooser now has a basic errorless implementation. --- src/main/java/frc/robot/RobotContainer.java | 2 +- .../autochooser/event/AutoChooserInputs.java | 8 +--- .../autochooser/event/AutoEventProvider.java | 44 +++++++++---------- .../event/AutoEventProviderIO.java | 5 ++- 4 files changed, 28 insertions(+), 31 deletions(-) diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index 5c7aa6d..aa61aef 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -103,7 +103,7 @@ public RobotVisualizer getRobotVisualizer() { return robotVisualizer; } - public Object getAutoChooser() { + public AutoChooser2025 getAutoChooser() { return autoChooser; } } diff --git a/src/main/java/frc/robot/autochooser/event/AutoChooserInputs.java b/src/main/java/frc/robot/autochooser/event/AutoChooserInputs.java index f307cec..11934d4 100644 --- a/src/main/java/frc/robot/autochooser/event/AutoChooserInputs.java +++ b/src/main/java/frc/robot/autochooser/event/AutoChooserInputs.java @@ -2,10 +2,10 @@ import frc.robot.autochooser.AutoAction; import frc.robot.autochooser.FieldLocation; -import frc.robot.utils.logging.subsystem.FolderLoggableInputs; import org.littletonrobotics.junction.LogTable; +import org.littletonrobotics.junction.inputs.LoggableInputs; -public class AutoChooserInputs extends FolderLoggableInputs { +public class AutoChooserInputs implements LoggableInputs { AutoAction action = AutoAction.INVALID; FieldLocation location = FieldLocation.INVALID; AutoAction defaultAction = AutoAction.INVALID; @@ -13,10 +13,6 @@ public class AutoChooserInputs extends FolderLoggableInputs { AutoAction feedbackAction = AutoAction.INVALID; FieldLocation feedbackLocation = FieldLocation.INVALID; - public AutoChooserInputs(String folder) { - super(folder); - } - @Override public void toLog(LogTable table) { table.put("action", action); diff --git a/src/main/java/frc/robot/autochooser/event/AutoEventProvider.java b/src/main/java/frc/robot/autochooser/event/AutoEventProvider.java index 277ac89..b34f9a8 100644 --- a/src/main/java/frc/robot/autochooser/event/AutoEventProvider.java +++ b/src/main/java/frc/robot/autochooser/event/AutoEventProvider.java @@ -3,7 +3,6 @@ import frc.robot.Robot; import frc.robot.autochooser.AutoAction; import frc.robot.autochooser.FieldLocation; -import frc.robot.utils.logging.subsystem.LoggableSystem; import java.util.function.BiFunction; import java.util.function.Consumer; @@ -12,37 +11,38 @@ * AutoActions} and {@link FieldLocation fieldLocations}
*/ public class AutoEventProvider { - private final LoggableSystem system; + private final AutoEventProviderIO io; + private final AutoChooserInputs inputs; private final BiFunction validator; private boolean changed = false; public AutoEventProvider( AutoEventProviderIO providerIO, BiFunction validator) { - this.system = new LoggableSystem<>(providerIO, new AutoChooserInputs("AutoChooser")); + this.io = providerIO; + this.inputs = new AutoChooserInputs(); this.validator = validator; setOnActionChangeListener((a) -> changed = true); setOnLocationChangeListener((l) -> changed = true); } public AutoAction getSelectedAction() { - return system.getInputs().action == null - ? system.getInputs().defaultAction - : system.getInputs().action; + return inputs.action == null + ? inputs.defaultAction + : inputs.action; } public FieldLocation getSelectedLocation() { - return system.getInputs().location == null - ? system.getInputs().defaultLocation - : system.getInputs().location; + return inputs.location == null + ? inputs.defaultLocation + : inputs.location; } public void updateInputs() { - FieldLocation lastsLoc = system.getInputs().location; - AutoAction lastsAct = system.getInputs().action; - system.updateInputs(); + FieldLocation lastsLoc = inputs.location; + AutoAction lastsAct = inputs.action; if (!Robot.isReal() - && (!lastsLoc.equals(system.getInputs().location) - || !lastsAct.equals(system.getInputs().action))) { + && (!lastsLoc.equals(inputs.location) + || !lastsAct.equals(inputs.action))) { changed = true; } if (changed) { @@ -52,25 +52,25 @@ public void updateInputs() { } public void setOnActionChangeListener(Consumer listener) { - system.getIO().setOnActionChangeListener(listener); + io.setOnActionChangeListener(listener); } public void setOnLocationChangeListener(Consumer listener) { - system.getIO().setOnLocationChangeListener(listener); + io.setOnLocationChangeListener(listener); } public void forceRefresh() { if (validator.apply(getSelectedAction(), getSelectedLocation())) { - system.getIO().setFeedbackAction(getSelectedAction()); - system.getIO().setFeedbackLocation(getSelectedLocation()); - system.getIO().runValidCommands(); + io.setFeedbackAction(getSelectedAction()); + io.setFeedbackLocation(getSelectedLocation()); + io.runValidCommands(); } else { - system.getIO().setFeedbackAction(AutoAction.INVALID); - system.getIO().setFeedbackLocation(FieldLocation.INVALID); + io.setFeedbackAction(AutoAction.INVALID); + io.setFeedbackLocation(FieldLocation.INVALID); } } public void addOnValidationCommand(Runnable c) { - system.getIO().addOnValidationCommand(c); + io.addOnValidationCommand(c); } } diff --git a/src/main/java/frc/robot/autochooser/event/AutoEventProviderIO.java b/src/main/java/frc/robot/autochooser/event/AutoEventProviderIO.java index 26e4b28..61f7f06 100644 --- a/src/main/java/frc/robot/autochooser/event/AutoEventProviderIO.java +++ b/src/main/java/frc/robot/autochooser/event/AutoEventProviderIO.java @@ -2,14 +2,13 @@ import frc.robot.autochooser.AutoAction; import frc.robot.autochooser.FieldLocation; -import frc.robot.utils.logging.LoggableIO; import java.util.function.Consumer; /** * interface that outlines the necessary methods to provide {@link FieldLocation FieldLocations} and * {@link AutoAction AutoActions} */ -public interface AutoEventProviderIO extends LoggableIO { +public interface AutoEventProviderIO { void setOnActionChangeListener(Consumer listener); void setOnLocationChangeListener(Consumer listener); @@ -21,4 +20,6 @@ public interface AutoEventProviderIO extends LoggableIO { void setFeedbackAction(AutoAction action); void setFeedbackLocation(FieldLocation location); + + void updateInputs(AutoChooserInputs inputs); } From f1ab6b7c1be97c76f6c60f51e32b21c8c0c11831 Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Sun, 18 Jan 2026 16:20:54 -0500 Subject: [PATCH 03/21] Refactored AutoChooser2025 as AutoChooser2026. --- src/main/java/frc/robot/RobotContainer.java | 8 ++++---- .../{AutoChooser2025.java => AutoChooser2026.java} | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) rename src/main/java/frc/robot/autochooser/chooser/{AutoChooser2025.java => AutoChooser2026.java} (95%) diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index aa61aef..2fd0533 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -8,7 +8,7 @@ import edu.wpi.first.wpilibj2.command.Command; import edu.wpi.first.wpilibj2.command.button.CommandXboxController; import edu.wpi.first.wpilibj2.command.button.Trigger; -import frc.robot.autochooser.chooser.AutoChooser2025; +import frc.robot.autochooser.chooser.AutoChooser2026; import frc.robot.commands.roller.SpinRoller; import frc.robot.commands.tilt.TiltDown; import frc.robot.commands.tilt.TiltUp; @@ -27,7 +27,7 @@ public class RobotContainer { private final RollerSubsystem rollerSubsystem; private final TiltSubsystem tiltSubsystem; private RobotVisualizer robotVisualizer = null; - private final AutoChooser2025 autoChooser; + private final AutoChooser2026 autoChooser; // Replace with CommandPS4Controller or CommandJoystick if needed //new CommandXboxController(OperatorConstants.kDriverControllerPort); @@ -54,7 +54,7 @@ public RobotContainer() { } configureBindings(); putShuffleboardCommands(); - autoChooser = new AutoChooser2025(null); + autoChooser = new AutoChooser2026(null); } /** @@ -103,7 +103,7 @@ public RobotVisualizer getRobotVisualizer() { return robotVisualizer; } - public AutoChooser2025 getAutoChooser() { + public AutoChooser2026 getAutoChooser() { return autoChooser; } } diff --git a/src/main/java/frc/robot/autochooser/chooser/AutoChooser2025.java b/src/main/java/frc/robot/autochooser/chooser/AutoChooser2026.java similarity index 95% rename from src/main/java/frc/robot/autochooser/chooser/AutoChooser2025.java rename to src/main/java/frc/robot/autochooser/chooser/AutoChooser2026.java index a5df7a3..ce47343 100644 --- a/src/main/java/frc/robot/autochooser/chooser/AutoChooser2025.java +++ b/src/main/java/frc/robot/autochooser/chooser/AutoChooser2026.java @@ -11,12 +11,12 @@ import frc.robot.utils.logging.commands.DoNothingCommand; import java.util.Map; -public class AutoChooser2025 extends SubsystemBase implements AutoChooser { +public class AutoChooser2026 extends SubsystemBase implements AutoChooser { private final Map commandMap; private final AutoEventProvider provider; // private final SwerveDrivetrain drivetrain; - public AutoChooser2025( + public AutoChooser2026( AutoEventProviderIO providerIO // SwerveDrivetrain drivetrain, ) { From b018e4a16f2f90ff22431eea7c19a50a852e7432 Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Fri, 23 Jan 2026 19:36:04 -0500 Subject: [PATCH 04/21] Fixed bug that silently passed null as a providerIO. --- src/main/java/frc/robot/RobotContainer.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index 2fd0533..8d51908 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -8,7 +8,10 @@ import edu.wpi.first.wpilibj2.command.Command; import edu.wpi.first.wpilibj2.command.button.CommandXboxController; import edu.wpi.first.wpilibj2.command.button.Trigger; +import frc.robot.autochooser.AutoAction; +import frc.robot.autochooser.FieldLocation; import frc.robot.autochooser.chooser.AutoChooser2026; +import frc.robot.autochooser.event.RealAutoEventProvider; import frc.robot.commands.roller.SpinRoller; import frc.robot.commands.tilt.TiltDown; import frc.robot.commands.tilt.TiltUp; @@ -54,7 +57,7 @@ public RobotContainer() { } configureBindings(); putShuffleboardCommands(); - autoChooser = new AutoChooser2026(null); + autoChooser = new AutoChooser2026(new RealAutoEventProvider(AutoAction.DO_NOTHING, FieldLocation.ZERO)); } /** From b562a1130d4ea2bfc1ef9d977acd6c935d1b5453 Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Fri, 30 Jan 2026 20:37:19 -0500 Subject: [PATCH 05/21] Implemented the AdvantageKit Autochooser. --- src/main/java/frc/robot/RobotContainer.java | 1 + .../autochooser/LoggedDashboardChooser.java | 172 ++++++++++++++++++ .../robot/autochooser/event/AutoEvent.java | 20 ++ 3 files changed, 193 insertions(+) create mode 100644 src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index 524474c..3429335 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -75,6 +75,7 @@ public RobotContainer() { } configureBindings(); putShuffleboardCommands(); + autoChooser = new AutoChooser2026(new RealAutoEventProvider(AutoAction.DO_NOTHING, FieldLocation.ZERO)); } SwerveInputStream driveAngularVelocity = SwerveInputStream.of(drivebase.getSwerveDrive(), () -> driveJoystick.getY() * -1, diff --git a/src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java b/src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java new file mode 100644 index 0000000..bd71e3a --- /dev/null +++ b/src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java @@ -0,0 +1,172 @@ +// Copyright (c) 2021-2026 Littleton Robotics +// http://github.com/Mechanical-Advantage +// +// Use of this source code is governed by a BSD +// license that can be found in the LICENSE file +// at the root directory of this project. + +package frc.robot.autochooser; + +import edu.wpi.first.wpilibj.smartdashboard.SendableChooser; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; +import frc.robot.autochooser.event.AutoEvent; +import frc.robot.utils.logging.commands.LoggableCommand; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; +import org.littletonrobotics.junction.LogTable; +import org.littletonrobotics.junction.Logger; +import org.littletonrobotics.junction.inputs.LoggableInputs; +import org.littletonrobotics.junction.networktables.LoggedNetworkInput; + +/** + * Manages a chooser value published to the "SmartDashboard" table of NT. + * + * @param The value type associated with each string key. + */ +public class LoggedDashboardChooser extends LoggedNetworkInput { + private final AutoEvent key; + private AutoEvent selectedValue = null; + private AutoEvent previousValue = null; + private SendableChooser sendableChooser = new SendableChooser<>(); + private Map options = new HashMap<>(); + private Consumer listener = null; + + private final LoggableInputs inputs = + new LoggableInputs() { + public void toLog(LogTable table) { + table.put(key.toString(), selectedValue.toString()); + } + + public void fromLog(LogTable table) { + selectedValue = AutoEvent.fromString(table.get(key.toString(), selectedValue.toString())); + } + }; + + /** + * Creates a new LoggedDashboardChooser, for handling a chooser input sent via NetworkTables. + * + * @param key The key for the chooser, published to "/SmartDashboard/{key}" for NT or + * "/DashboardInputs/SmartDashboard/{key}" when logged. + */ + public LoggedDashboardChooser(AutoEvent key) { + this.key = key; + SmartDashboard.putData(key.toString(), sendableChooser); + periodic(); + Logger.registerDashboardInput(this); + } + + /** + * Creates a new LoggedDashboardChooser, for handling a chooser input sent via NetworkTables. This + * constructor copies the options from a SendableChooser. Note that updates to the original + * SendableChooser will not affect this object. + * + * @param key The key for the chooser, published to "/SmartDashboard/{key}" for NT or + * "/DashboardInputs/{key}" when logged. + * @param chooser The existing SendableChooser object. + */ + @SuppressWarnings("unchecked") + public LoggedDashboardChooser(AutoEvent key, SendableChooser chooser) { + this(key); + + // Get options map + Map options = new HashMap<>(); + try { + Field mapField = SendableChooser.class.getDeclaredField("m_map"); + mapField.setAccessible(true); + options = (Map) mapField.get(chooser); + } catch (NoSuchFieldException + | SecurityException + | IllegalArgumentException + | IllegalAccessException e) { + e.printStackTrace(); + } + + // Get default option + String defaultString = ""; + try { + Field defaultField = SendableChooser.class.getDeclaredField("m_defaultChoice"); + defaultField.setAccessible(true); + defaultString = (String) defaultField.get(chooser); + } catch (NoSuchFieldException + | SecurityException + | IllegalArgumentException + | IllegalAccessException e) { + e.printStackTrace(); + } + + // Add options + for (AutoEvent optionKey : options.keySet()) { + if (optionKey.toString().equals(defaultString)) { + addDefaultOption(optionKey, options.get(optionKey)); + } else { + addOption(optionKey, options.get(optionKey)); + } + } + } + + /** + * Adds a new option to the chooser. + * + * @param key The string key for the option. + * @param value The value of the option. + */ + public void addOption(AutoEvent key, LoggableCommand value) { + sendableChooser.addOption(key.toString(), key); + options.put(key, value); + } + + /** + * Adds a new option to the chooser and sets it to the default. + * + * @param key The string key for the option. + * @param value The value of the option. + */ + public void addDefaultOption(AutoEvent key, LoggableCommand value) { + sendableChooser.setDefaultOption(key.toString(), key); + options.put(key, value); + } + + /** + * Returns the selected option. If there is none selected, it will return the default. If there is + * none selected and no default, then it will return {@code null}. + * + * @return The value for the selected option. + */ + public LoggableCommand get() { + return options.get(selectedValue); + } + + /** + * Binds the callback to run whenever the selected option changes. There can only be one listener, + * and this method overrites it with each invokation. + * + * @param listener The function to call that accepts the new value. + */ + public void onChange(Consumer listener) { + this.listener = listener; + } + + /** + * Returns the internal SendableChooser object, for use when setting up dashboard layouts. Do not + * read data from the SendableChooser directly. + * + * @return The internal SendableChooser object. + */ + public SendableChooser getSendableChooser() { + return sendableChooser; + } + + public void periodic() { + if (!Logger.hasReplaySource()) { + selectedValue = sendableChooser.getSelected(); + } + Logger.processInputs(prefix + "/SmartDashboard", inputs); + if (previousValue != selectedValue) { + if (listener != null) listener.accept(get()); + previousValue = selectedValue; + } + } +} diff --git a/src/main/java/frc/robot/autochooser/event/AutoEvent.java b/src/main/java/frc/robot/autochooser/event/AutoEvent.java index 977f323..6162eee 100644 --- a/src/main/java/frc/robot/autochooser/event/AutoEvent.java +++ b/src/main/java/frc/robot/autochooser/event/AutoEvent.java @@ -3,6 +3,8 @@ import frc.robot.autochooser.AutoAction; import frc.robot.autochooser.FieldLocation; import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Wrapper Class, that Contains a {@link frc.robot.autochooser.AutoAction} and a {@link @@ -37,4 +39,22 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(action, location); } + + @Override + public String toString() { + return "AutoEvent[action = " + action.toString() + ", location = " + location.toString() + "]"; + } + + public static AutoEvent fromString(String name) { + // Regex to capture the values inside 'action = ' and 'location = ' + Pattern pattern = Pattern.compile("AutoEvent\\[action = (.*), location = (.*)\\]"); + Matcher matcher = pattern.matcher(name); + + if (matcher.find()) { + AutoAction action = AutoAction.fromName(matcher.group(1)); + FieldLocation location = FieldLocation.fromName(matcher.group(2)); + return new AutoEvent(action, location); + } + throw new IllegalArgumentException("Invalid format"); + } } From 9c2f9a94aaac0fb970414c69c138f735ee7b690a Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Sat, 31 Jan 2026 11:44:49 -0500 Subject: [PATCH 06/21] Added chooser to robotContainer and fixed some errors. --- src/main/java/frc/robot/Robot.java | 3 -- src/main/java/frc/robot/RobotContainer.java | 32 ++++++++++++------- .../autochooser/LoggedDashboardChooser.java | 8 ++--- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/main/java/frc/robot/Robot.java b/src/main/java/frc/robot/Robot.java index 09f6e4a..c1c8280 100644 --- a/src/main/java/frc/robot/Robot.java +++ b/src/main/java/frc/robot/Robot.java @@ -115,9 +115,6 @@ public void robotPeriodic() { // Gets the alliance color. if (DriverStation.isDSAttached() && allianceColor.isEmpty()) { allianceColor = DriverStation.getAlliance(); - if (allianceColor.isPresent()) { - robotContainer.getAutoChooser().getProvider().forceRefresh(); - } } SmartDashboard.putNumber("driverXbox.getLeftY()",driverXbox.getLeftY()); SmartDashboard.putNumber("driverXbox::getRightX", driverXbox.getRightX()); diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index 3429335..672ec30 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -16,15 +16,11 @@ import frc.robot.commands.intake.SpinIntake; import frc.robot.autochooser.AutoAction; import frc.robot.autochooser.FieldLocation; -import frc.robot.autochooser.chooser.AutoChooser2026; -import frc.robot.autochooser.event.RealAutoEventProvider; -import frc.robot.commands.roller.SpinRoller; -import frc.robot.commands.tilt.TiltDown; -import frc.robot.commands.tilt.TiltUp; +import frc.robot.autochooser.LoggedDashboardChooser; +import frc.robot.autochooser.event.AutoEvent; import frc.robot.subsystems.IntakeSubsystem; -import frc.robot.subsystems.RollerSubsystem; -import frc.robot.subsystems.TiltSubsystem; import frc.robot.subsystems.swervedrive.SwerveSubsystem; +import frc.robot.utils.logging.commands.DoNothingCommand; import frc.robot.utils.simulation.RobotVisualizer; import swervelib.SwerveInputStream; @@ -43,8 +39,12 @@ public class RobotContainer { private final SwerveSubsystem drivebase = new SwerveSubsystem(new File(Filesystem.getDeployDirectory(),"YAGSL")); private final CommandJoystick driveJoystick = new CommandJoystick(Constants.DRIVE_JOYSTICK_PORT); private final CommandJoystick steerJoystick = new CommandJoystick(Constants.STEER_JOYSTICK_PORT); + // Instantiate the autochooser. + private final LoggedDashboardChooser autoChooser = new LoggedDashboardChooser( + // This is where you choose what the key is on the dashboard. + "Autonomous Chooser" + ); - private final AutoChooser2026 autoChooser; // Replace with CommandPS4Controller or CommandJoystick if needed //new CommandXboxController(OperatorConstants.kDriverControllerPort); @@ -75,7 +75,16 @@ public RobotContainer() { } configureBindings(); putShuffleboardCommands(); - autoChooser = new AutoChooser2026(new RealAutoEventProvider(AutoAction.DO_NOTHING, FieldLocation.ZERO)); + + // This is where options get added to the autoChooser. + autoChooser.addDefaultOption( // Adds a default option + new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.ZERO), // Adds an action and a location + new DoNothingCommand() // Adds a corresponding command + ); + // Adding more options using autoChooser.addOption(...) + autoChooser.addOption(new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.LEFT), new DoNothingCommand()); + autoChooser.addOption(new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.RIGHT), new DoNothingCommand()); + autoChooser.addOption(new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.MIDDLE), new DoNothingCommand()); } SwerveInputStream driveAngularVelocity = SwerveInputStream.of(drivebase.getSwerveDrive(), () -> driveJoystick.getY() * -1, @@ -133,14 +142,13 @@ public void putShuffleboardCommands() { * @return the command to run in autonomous */ public Command getAutonomousCommand() { - // An example command will be run in autonomous - return null; + return autoChooser.get(); } public RobotVisualizer getRobotVisualizer() { return robotVisualizer; } - public AutoChooser2026 getAutoChooser() { + public LoggedDashboardChooser getAutoChooser() { return autoChooser; } } diff --git a/src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java b/src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java index bd71e3a..6a1a95d 100644 --- a/src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java +++ b/src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java @@ -27,7 +27,7 @@ * @param The value type associated with each string key. */ public class LoggedDashboardChooser extends LoggedNetworkInput { - private final AutoEvent key; + private final String key; private AutoEvent selectedValue = null; private AutoEvent previousValue = null; private SendableChooser sendableChooser = new SendableChooser<>(); @@ -37,7 +37,7 @@ public class LoggedDashboardChooser extends LoggedNetworkInput { private final LoggableInputs inputs = new LoggableInputs() { public void toLog(LogTable table) { - table.put(key.toString(), selectedValue.toString()); + table.put(key, selectedValue.toString()); } public void fromLog(LogTable table) { @@ -51,7 +51,7 @@ public void fromLog(LogTable table) { * @param key The key for the chooser, published to "/SmartDashboard/{key}" for NT or * "/DashboardInputs/SmartDashboard/{key}" when logged. */ - public LoggedDashboardChooser(AutoEvent key) { + public LoggedDashboardChooser(String key) { this.key = key; SmartDashboard.putData(key.toString(), sendableChooser); periodic(); @@ -68,7 +68,7 @@ public LoggedDashboardChooser(AutoEvent key) { * @param chooser The existing SendableChooser object. */ @SuppressWarnings("unchecked") - public LoggedDashboardChooser(AutoEvent key, SendableChooser chooser) { + public LoggedDashboardChooser(String key, SendableChooser chooser) { this(key); // Get options map From 9cc422ec99cdb8b72e32fec1a15af2138e6ef026 Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Sat, 31 Jan 2026 12:48:31 -0500 Subject: [PATCH 07/21] Added "DoSomethingCommand" for harmless visible output. --- src/main/java/frc/robot/RobotContainer.java | 4 +++- .../autochooser/LoggedDashboardChooser.java | 10 ++++++---- .../logging/commands/DoSomethingCommand.java | 16 ++++++++++++++++ 3 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 src/main/java/frc/robot/utils/logging/commands/DoSomethingCommand.java diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index 672ec30..7751424 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -21,6 +21,7 @@ import frc.robot.subsystems.IntakeSubsystem; import frc.robot.subsystems.swervedrive.SwerveSubsystem; import frc.robot.utils.logging.commands.DoNothingCommand; +import frc.robot.utils.logging.commands.DoSomethingCommand; import frc.robot.utils.simulation.RobotVisualizer; import swervelib.SwerveInputStream; @@ -84,7 +85,8 @@ public RobotContainer() { // Adding more options using autoChooser.addOption(...) autoChooser.addOption(new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.LEFT), new DoNothingCommand()); autoChooser.addOption(new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.RIGHT), new DoNothingCommand()); - autoChooser.addOption(new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.MIDDLE), new DoNothingCommand()); + autoChooser.addOption(new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.MIDDLE), + new DoSomethingCommand("Did Something!")); } SwerveInputStream driveAngularVelocity = SwerveInputStream.of(drivebase.getSwerveDrive(), () -> driveJoystick.getY() * -1, diff --git a/src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java b/src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java index 6a1a95d..f917034 100644 --- a/src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java +++ b/src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java @@ -28,11 +28,12 @@ */ public class LoggedDashboardChooser extends LoggedNetworkInput { private final String key; - private AutoEvent selectedValue = null; + private AutoEvent selectedValue = new AutoEvent(AutoAction.INVALID, FieldLocation.INVALID); private AutoEvent previousValue = null; private SendableChooser sendableChooser = new SendableChooser<>(); private Map options = new HashMap<>(); private Consumer listener = null; + private boolean defaultSetYet = false; private final LoggableInputs inputs = new LoggableInputs() { @@ -41,7 +42,7 @@ public void toLog(LogTable table) { } public void fromLog(LogTable table) { - selectedValue = AutoEvent.fromString(table.get(key.toString(), selectedValue.toString())); + selectedValue = AutoEvent.fromString(table.get(key, selectedValue.toString())); } }; @@ -53,7 +54,7 @@ public void fromLog(LogTable table) { */ public LoggedDashboardChooser(String key) { this.key = key; - SmartDashboard.putData(key.toString(), sendableChooser); + SmartDashboard.putData(key, sendableChooser); periodic(); Logger.registerDashboardInput(this); } @@ -127,6 +128,7 @@ public void addOption(AutoEvent key, LoggableCommand value) { public void addDefaultOption(AutoEvent key, LoggableCommand value) { sendableChooser.setDefaultOption(key.toString(), key); options.put(key, value); + defaultSetYet = true; } /** @@ -160,7 +162,7 @@ public SendableChooser getSendableChooser() { } public void periodic() { - if (!Logger.hasReplaySource()) { + if (!Logger.hasReplaySource() && defaultSetYet) { selectedValue = sendableChooser.getSelected(); } Logger.processInputs(prefix + "/SmartDashboard", inputs); diff --git a/src/main/java/frc/robot/utils/logging/commands/DoSomethingCommand.java b/src/main/java/frc/robot/utils/logging/commands/DoSomethingCommand.java new file mode 100644 index 0000000..06c9e61 --- /dev/null +++ b/src/main/java/frc/robot/utils/logging/commands/DoSomethingCommand.java @@ -0,0 +1,16 @@ +package frc.robot.utils.logging.commands; + +public class DoSomethingCommand extends DoNothingCommand { + + private String message; + + public DoSomethingCommand(String message) { + this.message = message; + } + + @Override + public void execute() { + System.out.println(message); + } + +} From 72423d9fac78e7225ea02e735de1221c1f0e1056 Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Sat, 31 Jan 2026 13:12:12 -0500 Subject: [PATCH 08/21] Largened print message for DoSomethingCommand for better visibility in the logs. --- src/main/java/frc/robot/RobotContainer.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index 7751424..3fb075b 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -86,7 +86,16 @@ public RobotContainer() { autoChooser.addOption(new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.LEFT), new DoNothingCommand()); autoChooser.addOption(new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.RIGHT), new DoNothingCommand()); autoChooser.addOption(new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.MIDDLE), - new DoSomethingCommand("Did Something!")); + new DoSomethingCommand(""" + + SUCCESSFULLY + + DID + + SOMETHING + + + """)); // Bigger print message is easier to see in the logs. } SwerveInputStream driveAngularVelocity = SwerveInputStream.of(drivebase.getSwerveDrive(), () -> driveJoystick.getY() * -1, From c055bf57404d1396f2e7a016951156eb023959ba Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Sat, 31 Jan 2026 13:23:42 -0500 Subject: [PATCH 09/21] Deleted old autochooser files, cleaned up branch. --- src/main/java/frc/robot/RobotContainer.java | 2 +- .../autochooser/{event => }/AutoEvent.java | 4 +- .../autochooser/LoggedDashboardChooser.java | 1 - .../autochooser/chooser/AutoChooser.java | 16 --- .../autochooser/chooser/AutoChooser2026.java | 59 --------- .../autochooser/event/AutoChooserInputs.java | 35 ----- .../autochooser/event/AutoEventProvider.java | 76 ----------- .../event/AutoEventProviderIO.java | 25 ---- .../event/RealAutoEventProvider.java | 121 ------------------ 9 files changed, 2 insertions(+), 337 deletions(-) rename src/main/java/frc/robot/autochooser/{event => }/AutoEvent.java (93%) delete mode 100644 src/main/java/frc/robot/autochooser/chooser/AutoChooser.java delete mode 100644 src/main/java/frc/robot/autochooser/chooser/AutoChooser2026.java delete mode 100644 src/main/java/frc/robot/autochooser/event/AutoChooserInputs.java delete mode 100644 src/main/java/frc/robot/autochooser/event/AutoEventProvider.java delete mode 100644 src/main/java/frc/robot/autochooser/event/AutoEventProviderIO.java delete mode 100644 src/main/java/frc/robot/autochooser/event/RealAutoEventProvider.java diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index 3fb075b..cffe39c 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -17,7 +17,7 @@ import frc.robot.autochooser.AutoAction; import frc.robot.autochooser.FieldLocation; import frc.robot.autochooser.LoggedDashboardChooser; -import frc.robot.autochooser.event.AutoEvent; +import frc.robot.autochooser.AutoEvent; import frc.robot.subsystems.IntakeSubsystem; import frc.robot.subsystems.swervedrive.SwerveSubsystem; import frc.robot.utils.logging.commands.DoNothingCommand; diff --git a/src/main/java/frc/robot/autochooser/event/AutoEvent.java b/src/main/java/frc/robot/autochooser/AutoEvent.java similarity index 93% rename from src/main/java/frc/robot/autochooser/event/AutoEvent.java rename to src/main/java/frc/robot/autochooser/AutoEvent.java index 6162eee..b7cca43 100644 --- a/src/main/java/frc/robot/autochooser/event/AutoEvent.java +++ b/src/main/java/frc/robot/autochooser/AutoEvent.java @@ -1,7 +1,5 @@ -package frc.robot.autochooser.event; +package frc.robot.autochooser; -import frc.robot.autochooser.AutoAction; -import frc.robot.autochooser.FieldLocation; import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java b/src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java index f917034..d57a8af 100644 --- a/src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java +++ b/src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java @@ -9,7 +9,6 @@ import edu.wpi.first.wpilibj.smartdashboard.SendableChooser; import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; -import frc.robot.autochooser.event.AutoEvent; import frc.robot.utils.logging.commands.LoggableCommand; import java.lang.reflect.Field; diff --git a/src/main/java/frc/robot/autochooser/chooser/AutoChooser.java b/src/main/java/frc/robot/autochooser/chooser/AutoChooser.java deleted file mode 100644 index f2edea8..0000000 --- a/src/main/java/frc/robot/autochooser/chooser/AutoChooser.java +++ /dev/null @@ -1,16 +0,0 @@ -package frc.robot.autochooser.chooser; - -import edu.wpi.first.math.geometry.Pose2d; -import edu.wpi.first.wpilibj2.command.Command; -import frc.robot.autochooser.event.AutoEvent; - -/** interface for taking in a {@link AutoEvent} and returning the corresponding {@link Command} */ -public interface AutoChooser { - /** - * @return Command that corresponds to the selected {@link AutoEvent} from the {@link - * frc.robot.autochooser.event.AutoEventProvider} - */ - Command getAutoCommand(); - - Pose2d getStartingPosition(); -} diff --git a/src/main/java/frc/robot/autochooser/chooser/AutoChooser2026.java b/src/main/java/frc/robot/autochooser/chooser/AutoChooser2026.java deleted file mode 100644 index ce47343..0000000 --- a/src/main/java/frc/robot/autochooser/chooser/AutoChooser2026.java +++ /dev/null @@ -1,59 +0,0 @@ -package frc.robot.autochooser.chooser; - -import edu.wpi.first.math.geometry.Pose2d; -import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.SubsystemBase; -import frc.robot.autochooser.AutoAction; -import frc.robot.autochooser.FieldLocation; -import frc.robot.autochooser.event.AutoEvent; -import frc.robot.autochooser.event.AutoEventProvider; -import frc.robot.autochooser.event.AutoEventProviderIO; -import frc.robot.utils.logging.commands.DoNothingCommand; -import java.util.Map; - -public class AutoChooser2026 extends SubsystemBase implements AutoChooser { - private final Map commandMap; - private final AutoEventProvider provider; - // private final SwerveDrivetrain drivetrain; - - public AutoChooser2026( - AutoEventProviderIO providerIO - // SwerveDrivetrain drivetrain, - ) { - provider = new AutoEventProvider(providerIO, this::isValid); - // this.drivetrain = drivetrain; - commandMap = - Map.ofEntries( - Map.entry( - new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.LEFT), new DoNothingCommand()), - Map.entry( - new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.MIDDLE), new DoNothingCommand()), - Map.entry( - new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.RIGHT), new DoNothingCommand()) - ); - } - - @Override - public Command getAutoCommand() { - return commandMap.get( - new AutoEvent(provider.getSelectedAction(), provider.getSelectedLocation())); - } - - @Override - public Pose2d getStartingPosition() { - return provider.getSelectedLocation().getLocation(); - } - - protected boolean isValid(AutoAction action, FieldLocation location) { - return commandMap.containsKey(new AutoEvent(action, location)); - } - - @Override - public void periodic() { - provider.updateInputs(); - } - - public AutoEventProvider getProvider() { - return provider; - } -} diff --git a/src/main/java/frc/robot/autochooser/event/AutoChooserInputs.java b/src/main/java/frc/robot/autochooser/event/AutoChooserInputs.java deleted file mode 100644 index 11934d4..0000000 --- a/src/main/java/frc/robot/autochooser/event/AutoChooserInputs.java +++ /dev/null @@ -1,35 +0,0 @@ -package frc.robot.autochooser.event; - -import frc.robot.autochooser.AutoAction; -import frc.robot.autochooser.FieldLocation; -import org.littletonrobotics.junction.LogTable; -import org.littletonrobotics.junction.inputs.LoggableInputs; - -public class AutoChooserInputs implements LoggableInputs { - AutoAction action = AutoAction.INVALID; - FieldLocation location = FieldLocation.INVALID; - AutoAction defaultAction = AutoAction.INVALID; - FieldLocation defaultLocation = FieldLocation.INVALID; - AutoAction feedbackAction = AutoAction.INVALID; - FieldLocation feedbackLocation = FieldLocation.INVALID; - - @Override - public void toLog(LogTable table) { - table.put("action", action); - table.put("location", location); - table.put("defaultAction", defaultAction); - table.put("defaultLocation", defaultLocation); - table.put("feedbackAction", feedbackAction); - table.put("feedbackLocation", feedbackLocation); - } - - @Override - public void fromLog(LogTable table) { - action = table.get("action", action); - location = table.get("location", location); - defaultAction = table.get("defaultAction", defaultAction); - defaultLocation = table.get("defaultLocation", defaultLocation); - feedbackAction = table.get("feedbackAction", feedbackAction); - feedbackLocation = table.get("feedbackLocation", feedbackLocation); - } -} diff --git a/src/main/java/frc/robot/autochooser/event/AutoEventProvider.java b/src/main/java/frc/robot/autochooser/event/AutoEventProvider.java deleted file mode 100644 index b34f9a8..0000000 --- a/src/main/java/frc/robot/autochooser/event/AutoEventProvider.java +++ /dev/null @@ -1,76 +0,0 @@ -package frc.robot.autochooser.event; - -import frc.robot.Robot; -import frc.robot.autochooser.AutoAction; -import frc.robot.autochooser.FieldLocation; -import java.util.function.BiFunction; -import java.util.function.Consumer; - -/** - * Superclass of {@link AutoEventProviderIO} that uses Network Tables to get {@link AutoAction - * AutoActions} and {@link FieldLocation fieldLocations}
- */ -public class AutoEventProvider { - private final AutoEventProviderIO io; - private final AutoChooserInputs inputs; - private final BiFunction validator; - private boolean changed = false; - - public AutoEventProvider( - AutoEventProviderIO providerIO, BiFunction validator) { - this.io = providerIO; - this.inputs = new AutoChooserInputs(); - this.validator = validator; - setOnActionChangeListener((a) -> changed = true); - setOnLocationChangeListener((l) -> changed = true); - } - - public AutoAction getSelectedAction() { - return inputs.action == null - ? inputs.defaultAction - : inputs.action; - } - - public FieldLocation getSelectedLocation() { - return inputs.location == null - ? inputs.defaultLocation - : inputs.location; - } - - public void updateInputs() { - FieldLocation lastsLoc = inputs.location; - AutoAction lastsAct = inputs.action; - if (!Robot.isReal() - && (!lastsLoc.equals(inputs.location) - || !lastsAct.equals(inputs.action))) { - changed = true; - } - if (changed) { - forceRefresh(); - changed = false; - } - } - - public void setOnActionChangeListener(Consumer listener) { - io.setOnActionChangeListener(listener); - } - - public void setOnLocationChangeListener(Consumer listener) { - io.setOnLocationChangeListener(listener); - } - - public void forceRefresh() { - if (validator.apply(getSelectedAction(), getSelectedLocation())) { - io.setFeedbackAction(getSelectedAction()); - io.setFeedbackLocation(getSelectedLocation()); - io.runValidCommands(); - } else { - io.setFeedbackAction(AutoAction.INVALID); - io.setFeedbackLocation(FieldLocation.INVALID); - } - } - - public void addOnValidationCommand(Runnable c) { - io.addOnValidationCommand(c); - } -} diff --git a/src/main/java/frc/robot/autochooser/event/AutoEventProviderIO.java b/src/main/java/frc/robot/autochooser/event/AutoEventProviderIO.java deleted file mode 100644 index 61f7f06..0000000 --- a/src/main/java/frc/robot/autochooser/event/AutoEventProviderIO.java +++ /dev/null @@ -1,25 +0,0 @@ -package frc.robot.autochooser.event; - -import frc.robot.autochooser.AutoAction; -import frc.robot.autochooser.FieldLocation; -import java.util.function.Consumer; - -/** - * interface that outlines the necessary methods to provide {@link FieldLocation FieldLocations} and - * {@link AutoAction AutoActions} - */ -public interface AutoEventProviderIO { - void setOnActionChangeListener(Consumer listener); - - void setOnLocationChangeListener(Consumer listener); - - void addOnValidationCommand(Runnable consumer); - - void runValidCommands(); - - void setFeedbackAction(AutoAction action); - - void setFeedbackLocation(FieldLocation location); - - void updateInputs(AutoChooserInputs inputs); -} diff --git a/src/main/java/frc/robot/autochooser/event/RealAutoEventProvider.java b/src/main/java/frc/robot/autochooser/event/RealAutoEventProvider.java deleted file mode 100644 index 946a3bb..0000000 --- a/src/main/java/frc/robot/autochooser/event/RealAutoEventProvider.java +++ /dev/null @@ -1,121 +0,0 @@ -package frc.robot.autochooser.event; - -import edu.wpi.first.networktables.NetworkTableValue; -import edu.wpi.first.wpilibj.shuffleboard.BuiltInWidgets; -import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; -import edu.wpi.first.wpilibj.shuffleboard.ShuffleboardTab; -import edu.wpi.first.wpilibj.smartdashboard.SendableChooser; -import frc.robot.autochooser.AutoAction; -import frc.robot.autochooser.FieldLocation; -import frc.robot.utils.shuffleboard.SmartShuffleboard; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.function.Consumer; - -public class RealAutoEventProvider implements AutoEventProviderIO { - - public static final String AUTO_TAB_NAME = "Auto"; - public static final String ACTION_FIELD_NAME = "Auto Action"; - public static final String LOCATION_FIELD_NAME = "Location Chooser"; - public static final String AUTO_LOCATION_FEEDBACK_NAME = "FieldLocationFeedback"; - public static final String AUTO_ACTION_FEEDBACK_NAME = "AutoActionFeedback"; - - private final SendableChooser actionChooser; - private final SendableChooser locationChooser; - private final AutoAction defaultAutoAction; - private final FieldLocation defaultFieldLocation; - public final List onValidEvents = new ArrayList<>(); - - public RealAutoEventProvider(AutoAction defaultAutoAction, FieldLocation defaultFieldLocation) { - this.defaultAutoAction = defaultAutoAction; - this.defaultFieldLocation = defaultFieldLocation; - this.actionChooser = new SendableChooser<>(); - this.locationChooser = new SendableChooser<>(); - Arrays.stream(AutoAction.values()).forEach(a -> actionChooser.addOption(a.getName(), a)); - Arrays.stream(FieldLocation.values()) - .forEach(l -> locationChooser.addOption(l.getShuffleboardName(), l)); - actionChooser.setDefaultOption(defaultAutoAction.getName(), defaultAutoAction); - locationChooser.setDefaultOption( - defaultFieldLocation.getShuffleboardName(), defaultFieldLocation); - ShuffleboardTab autoTab = Shuffleboard.getTab(AUTO_TAB_NAME); - autoTab - .add(ACTION_FIELD_NAME, actionChooser) - .withWidget(BuiltInWidgets.kComboBoxChooser) - .withPosition(0, 0) - .withSize(4, 1); - autoTab.add(LOCATION_FIELD_NAME, locationChooser).withPosition(0, 1).withSize(4, 1); - SmartShuffleboard.put(AUTO_TAB_NAME, AUTO_ACTION_FEEDBACK_NAME, defaultAutoAction.toString()) - .withPosition(2, 2) - .withSize(2, 1); - SmartShuffleboard.put( - AUTO_TAB_NAME, AUTO_LOCATION_FEEDBACK_NAME, defaultFieldLocation.getShuffleboardName()) - .withPosition(0, 2) - .withSize(2, 1); - } - - /** - * @param listener function to be called when the value in {@link #actionChooser} changes - */ - @Override - public void setOnActionChangeListener(Consumer listener) { - actionChooser.onChange(listener); - } - - /** - * @param listener function to be called when the value in {@link #locationChooser} changes - */ - @Override - public void setOnLocationChangeListener(Consumer listener) { - locationChooser.onChange(listener); - } - - @Override - public void addOnValidationCommand(Runnable consumer) { - onValidEvents.add(consumer); - } - - @Override - public void runValidCommands() { - onValidEvents.forEach( - c -> { - try { - c.run(); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - } - - @Override - public void setFeedbackAction(AutoAction action) { - SmartShuffleboard.put(AUTO_TAB_NAME, AUTO_ACTION_FEEDBACK_NAME, action.toString()); - } - - @Override - public void setFeedbackLocation(FieldLocation location) { - SmartShuffleboard.put( - AUTO_TAB_NAME, AUTO_LOCATION_FEEDBACK_NAME, location.getShuffleboardName()); - } - - @Override - public void updateInputs(AutoChooserInputs inputs) { - inputs.action = actionChooser.getSelected(); - inputs.location = locationChooser.getSelected(); - inputs.defaultAction = defaultAutoAction; - inputs.defaultLocation = defaultFieldLocation; - NetworkTableValue feedbackLocation = - SmartShuffleboard.getValue(AUTO_TAB_NAME, AUTO_LOCATION_FEEDBACK_NAME); - if (feedbackLocation == null || feedbackLocation.getString().isBlank()) { - inputs.feedbackLocation = FieldLocation.INVALID; - } else { - inputs.feedbackLocation = FieldLocation.fromName(feedbackLocation.getString()); - } - NetworkTableValue action = SmartShuffleboard.getValue(AUTO_TAB_NAME, AUTO_ACTION_FEEDBACK_NAME); - if (action == null || action.getString().isBlank()) { - inputs.feedbackAction = AutoAction.INVALID; - } else { - inputs.feedbackAction = AutoAction.fromName(action.toString()); - } - } -} From 8e7767ec90e420fe63f516e6136bb5e19b7e7998 Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Sun, 1 Feb 2026 13:21:52 -0500 Subject: [PATCH 10/21] I made the AutoChooser extend LoggedDashboardChooser rather than be an edited copy of it. --- src/main/java/frc/robot/RobotContainer.java | 6 +- .../frc/robot/autochooser/AutoChooser.java | 21 +++ .../autochooser/LoggedDashboardChooser.java | 173 ------------------ 3 files changed, 24 insertions(+), 176 deletions(-) create mode 100644 src/main/java/frc/robot/autochooser/AutoChooser.java delete mode 100644 src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index a2d20a1..e07707a 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -17,8 +17,8 @@ import frc.robot.commands.drive.DriveDirectionTime; import frc.robot.commands.intake.SpinIntake; import frc.robot.autochooser.AutoAction; +import frc.robot.autochooser.AutoChooser; import frc.robot.autochooser.FieldLocation; -import frc.robot.autochooser.LoggedDashboardChooser; import frc.robot.autochooser.AutoEvent; import frc.robot.subsystems.IntakeSubsystem; import frc.robot.subsystems.swervedrive.SwerveSubsystem; @@ -48,7 +48,7 @@ public class RobotContainer { private final CommandJoystick driveJoystick = new CommandJoystick(Constants.DRIVE_JOYSTICK_PORT); private final CommandJoystick steerJoystick = new CommandJoystick(Constants.STEER_JOYSTICK_PORT); // Instantiate the autochooser. - private final LoggedDashboardChooser autoChooser = new LoggedDashboardChooser( + private final AutoChooser autoChooser = new AutoChooser( // This is where you choose what the key is on the dashboard. "Autonomous Chooser" ); @@ -182,7 +182,7 @@ public RobotVisualizer getRobotVisualizer() { return robotVisualizer; } - public LoggedDashboardChooser getAutoChooser() { + public AutoChooser getAutoChooser() { return autoChooser; } diff --git a/src/main/java/frc/robot/autochooser/AutoChooser.java b/src/main/java/frc/robot/autochooser/AutoChooser.java new file mode 100644 index 0000000..eff1a7a --- /dev/null +++ b/src/main/java/frc/robot/autochooser/AutoChooser.java @@ -0,0 +1,21 @@ +package frc.robot.autochooser; + +import org.littletonrobotics.junction.networktables.LoggedDashboardChooser; + +import frc.robot.utils.logging.commands.LoggableCommand; + +public class AutoChooser extends LoggedDashboardChooser { + + public AutoChooser(String key) { + super(key); + } + + public void addDefaultOption(AutoEvent key, LoggableCommand value) { + super.addDefaultOption(key.toString(), value); + } + + public void addOption(AutoEvent key, LoggableCommand value) { + super.addOption(key.toString(), value); + } + +} diff --git a/src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java b/src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java deleted file mode 100644 index d57a8af..0000000 --- a/src/main/java/frc/robot/autochooser/LoggedDashboardChooser.java +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (c) 2021-2026 Littleton Robotics -// http://github.com/Mechanical-Advantage -// -// Use of this source code is governed by a BSD -// license that can be found in the LICENSE file -// at the root directory of this project. - -package frc.robot.autochooser; - -import edu.wpi.first.wpilibj.smartdashboard.SendableChooser; -import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; -import frc.robot.utils.logging.commands.LoggableCommand; - -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Consumer; -import org.littletonrobotics.junction.LogTable; -import org.littletonrobotics.junction.Logger; -import org.littletonrobotics.junction.inputs.LoggableInputs; -import org.littletonrobotics.junction.networktables.LoggedNetworkInput; - -/** - * Manages a chooser value published to the "SmartDashboard" table of NT. - * - * @param The value type associated with each string key. - */ -public class LoggedDashboardChooser extends LoggedNetworkInput { - private final String key; - private AutoEvent selectedValue = new AutoEvent(AutoAction.INVALID, FieldLocation.INVALID); - private AutoEvent previousValue = null; - private SendableChooser sendableChooser = new SendableChooser<>(); - private Map options = new HashMap<>(); - private Consumer listener = null; - private boolean defaultSetYet = false; - - private final LoggableInputs inputs = - new LoggableInputs() { - public void toLog(LogTable table) { - table.put(key, selectedValue.toString()); - } - - public void fromLog(LogTable table) { - selectedValue = AutoEvent.fromString(table.get(key, selectedValue.toString())); - } - }; - - /** - * Creates a new LoggedDashboardChooser, for handling a chooser input sent via NetworkTables. - * - * @param key The key for the chooser, published to "/SmartDashboard/{key}" for NT or - * "/DashboardInputs/SmartDashboard/{key}" when logged. - */ - public LoggedDashboardChooser(String key) { - this.key = key; - SmartDashboard.putData(key, sendableChooser); - periodic(); - Logger.registerDashboardInput(this); - } - - /** - * Creates a new LoggedDashboardChooser, for handling a chooser input sent via NetworkTables. This - * constructor copies the options from a SendableChooser. Note that updates to the original - * SendableChooser will not affect this object. - * - * @param key The key for the chooser, published to "/SmartDashboard/{key}" for NT or - * "/DashboardInputs/{key}" when logged. - * @param chooser The existing SendableChooser object. - */ - @SuppressWarnings("unchecked") - public LoggedDashboardChooser(String key, SendableChooser chooser) { - this(key); - - // Get options map - Map options = new HashMap<>(); - try { - Field mapField = SendableChooser.class.getDeclaredField("m_map"); - mapField.setAccessible(true); - options = (Map) mapField.get(chooser); - } catch (NoSuchFieldException - | SecurityException - | IllegalArgumentException - | IllegalAccessException e) { - e.printStackTrace(); - } - - // Get default option - String defaultString = ""; - try { - Field defaultField = SendableChooser.class.getDeclaredField("m_defaultChoice"); - defaultField.setAccessible(true); - defaultString = (String) defaultField.get(chooser); - } catch (NoSuchFieldException - | SecurityException - | IllegalArgumentException - | IllegalAccessException e) { - e.printStackTrace(); - } - - // Add options - for (AutoEvent optionKey : options.keySet()) { - if (optionKey.toString().equals(defaultString)) { - addDefaultOption(optionKey, options.get(optionKey)); - } else { - addOption(optionKey, options.get(optionKey)); - } - } - } - - /** - * Adds a new option to the chooser. - * - * @param key The string key for the option. - * @param value The value of the option. - */ - public void addOption(AutoEvent key, LoggableCommand value) { - sendableChooser.addOption(key.toString(), key); - options.put(key, value); - } - - /** - * Adds a new option to the chooser and sets it to the default. - * - * @param key The string key for the option. - * @param value The value of the option. - */ - public void addDefaultOption(AutoEvent key, LoggableCommand value) { - sendableChooser.setDefaultOption(key.toString(), key); - options.put(key, value); - defaultSetYet = true; - } - - /** - * Returns the selected option. If there is none selected, it will return the default. If there is - * none selected and no default, then it will return {@code null}. - * - * @return The value for the selected option. - */ - public LoggableCommand get() { - return options.get(selectedValue); - } - - /** - * Binds the callback to run whenever the selected option changes. There can only be one listener, - * and this method overrites it with each invokation. - * - * @param listener The function to call that accepts the new value. - */ - public void onChange(Consumer listener) { - this.listener = listener; - } - - /** - * Returns the internal SendableChooser object, for use when setting up dashboard layouts. Do not - * read data from the SendableChooser directly. - * - * @return The internal SendableChooser object. - */ - public SendableChooser getSendableChooser() { - return sendableChooser; - } - - public void periodic() { - if (!Logger.hasReplaySource() && defaultSetYet) { - selectedValue = sendableChooser.getSelected(); - } - Logger.processInputs(prefix + "/SmartDashboard", inputs); - if (previousValue != selectedValue) { - if (listener != null) listener.accept(get()); - previousValue = selectedValue; - } - } -} From febd78c0304563c1ee7e3b29fa649d5a63225449 Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Sun, 1 Feb 2026 14:03:04 -0500 Subject: [PATCH 11/21] Fixed error due to changing the name of a method. --- src/main/java/frc/robot/autochooser/FieldLocation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/frc/robot/autochooser/FieldLocation.java b/src/main/java/frc/robot/autochooser/FieldLocation.java index bb8ae60..43e21ef 100644 --- a/src/main/java/frc/robot/autochooser/FieldLocation.java +++ b/src/main/java/frc/robot/autochooser/FieldLocation.java @@ -42,7 +42,7 @@ public static FieldLocation fromName(String string) { } public Pose2d getLocation() { - Alliance alliance = Robot.getAllianceColor().orElse(null); + Alliance alliance = Robot.allianceColor().orElse(null); if (alliance == null) { return new Pose2d(INVALID.xPose, INVALID.yPose, Rotation2d.fromDegrees(INVALID.angle)); } From 7589b95a4bffc1d8b63dacff7bcb984c005b3f89 Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Mon, 2 Feb 2026 20:35:33 -0500 Subject: [PATCH 12/21] Created two choosers instead of one to clean up the interface on elastic. --- src/main/java/frc/robot/RobotContainer.java | 27 +------ .../frc/robot/autochooser/AutoChooser.java | 77 +++++++++++++++++-- .../frc/robot/autochooser/AutoCommand.java | 45 +++++++++++ 3 files changed, 116 insertions(+), 33 deletions(-) create mode 100644 src/main/java/frc/robot/autochooser/AutoCommand.java diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index e07707a..b8acae2 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -48,10 +48,7 @@ public class RobotContainer { private final CommandJoystick driveJoystick = new CommandJoystick(Constants.DRIVE_JOYSTICK_PORT); private final CommandJoystick steerJoystick = new CommandJoystick(Constants.STEER_JOYSTICK_PORT); // Instantiate the autochooser. - private final AutoChooser autoChooser = new AutoChooser( - // This is where you choose what the key is on the dashboard. - "Autonomous Chooser" - ); + private final AutoChooser autoChooser = new AutoChooser(); // The robot's subsystems and commands are defined here... //private final TiltSubsystem tiltSubsystem; private SwerveSubsystem drivebase = null; @@ -94,26 +91,6 @@ public RobotContainer() { configureBindings(); putShuffleboardCommands(); - // This is where options get added to the autoChooser. - autoChooser.addDefaultOption( // Adds a default option - new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.ZERO), // Adds an action and a location - new DoNothingCommand() // Adds a corresponding command - ); - // Adding more options using autoChooser.addOption(...) - autoChooser.addOption(new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.LEFT), new DoNothingCommand()); - autoChooser.addOption(new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.RIGHT), new DoNothingCommand()); - autoChooser.addOption(new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.MIDDLE), - new DoSomethingCommand(""" - - SUCCESSFULLY - - DID - - SOMETHING - - - """) // Bigger print message is easier to see in the logs. - ); } /** * Use this method to define your trigger->command mappings. Triggers can be created via the @@ -176,7 +153,7 @@ public void putShuffleboardCommands() { * @return the command to run in autonomous */ public Command getAutonomousCommand() { - return autoChooser.get(); + return autoChooser.getCommand(); } public RobotVisualizer getRobotVisualizer() { return robotVisualizer; diff --git a/src/main/java/frc/robot/autochooser/AutoChooser.java b/src/main/java/frc/robot/autochooser/AutoChooser.java index eff1a7a..941696f 100644 --- a/src/main/java/frc/robot/autochooser/AutoChooser.java +++ b/src/main/java/frc/robot/autochooser/AutoChooser.java @@ -1,21 +1,82 @@ package frc.robot.autochooser; +import java.util.HashMap; +import java.util.Map; + import org.littletonrobotics.junction.networktables.LoggedDashboardChooser; +import frc.robot.utils.logging.commands.DoNothingCommand; +import frc.robot.utils.logging.commands.DoSomethingCommand; import frc.robot.utils.logging.commands.LoggableCommand; -public class AutoChooser extends LoggedDashboardChooser { - - public AutoChooser(String key) { - super(key); +public class AutoChooser { + + /** Drop-down chooser for the location. */ + private LoggedDashboardChooser locationChooser; + /** Drop-down chooser for the action. */ + private LoggedDashboardChooser actionChooser; + /** Structure for mapping possible choices to commands. */ + private final Map commandMap = new HashMap<>(); + + private final AutoCommand DEFAULT_COMMAND = AutoCommand.DoNothingCommand; + + public AutoChooser() { + this.locationChooser = new LoggedDashboardChooser<>( + "Location Chooser" + ); + this.actionChooser = new LoggedDashboardChooser<>( + "Action Chooser" + ); + populateChoosers(); + populateMap(); + } + + /** Populates the drop-down choosers with enum constants. */ + private void populateChoosers() { + for (FieldLocation location : FieldLocation.values()) { + switch (location) { + case INVALID -> {} // Skip the invalid case. + case ZERO -> { // Default + locationChooser.addDefaultOption(location.toString(), location); + } + default -> {locationChooser.addOption(location.toString(), location);} + }; + } + for (AutoAction action : AutoAction.values()) { + switch (action) { + case INVALID -> {} // Skip the invalid case. + case DO_NOTHING -> { // Default + actionChooser.addDefaultOption(action.toString(), action); + } + default -> {actionChooser.addOption(action.toString(), action);} + }; + } + } + + /** Put mappings here. + * @see AutoCommand */ + private void populateMap() { + // Currently, we have some example mappings. + commandMap.put(new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.LEFT), + AutoCommand.DoNothingCommand); + commandMap.put(new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.RIGHT), + AutoCommand.DoSomethingCommand); + } + + private AutoCommand get() { + AutoAction chosenAction = actionChooser.get(); + FieldLocation chosenLocation = locationChooser.get(); + AutoEvent event = new AutoEvent(chosenAction, chosenLocation); + + return commandMap.getOrDefault(event, DEFAULT_COMMAND); } - public void addDefaultOption(AutoEvent key, LoggableCommand value) { - super.addDefaultOption(key.toString(), value); + public LoggableCommand getCommand() { + return get().getCommand(); } - public void addOption(AutoEvent key, LoggableCommand value) { - super.addOption(key.toString(), value); + public String getCommandDescription() { + return get().getDescription(); } } diff --git a/src/main/java/frc/robot/autochooser/AutoCommand.java b/src/main/java/frc/robot/autochooser/AutoCommand.java new file mode 100644 index 0000000..ccfc303 --- /dev/null +++ b/src/main/java/frc/robot/autochooser/AutoCommand.java @@ -0,0 +1,45 @@ +package frc.robot.autochooser; + +import frc.robot.utils.logging.commands.LoggableCommand; +import frc.robot.utils.logging.commands.DoNothingCommand; +import frc.robot.utils.logging.commands.DoSomethingCommand; + +public enum AutoCommand { + + // Add commands here. Importantly, you should give each command + // a readable description so that the drive team can tell what + // the robot will actually do. This will be used to give the + // drive team visual feedback on the elastic dashboard when + // selecting an autonoumous command. + DoNothingCommand( + "The robot will do nothing.", + new DoNothingCommand() + ), + DoSomethingCommand( + "This will just print something to the terminal.", + new DoSomethingCommand(""" + SUCCESSFULLY + + DID + + SOMETHING + """) + ); + + private String description; + private LoggableCommand command; + + AutoCommand(String description, LoggableCommand command) { + this.description = description; + this.command = command; + } + + public String getDescription() { + return description; + } + + public LoggableCommand getCommand() { + return command; + } + +} From 8b6eb6dffd4d85edce72ea0c7800456926466255 Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Mon, 2 Feb 2026 20:44:45 -0500 Subject: [PATCH 13/21] Set up an area on the elastic dashboard for visual feedback on the selected command for the drive team. --- src/main/java/frc/robot/Robot.java | 2 ++ src/main/java/frc/robot/RobotContainer.java | 1 + src/main/java/frc/robot/autochooser/AutoChooser.java | 3 +-- src/main/java/frc/robot/autochooser/AutoCommand.java | 5 +++-- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/frc/robot/Robot.java b/src/main/java/frc/robot/Robot.java index cd483ab..3bd14b7 100644 --- a/src/main/java/frc/robot/Robot.java +++ b/src/main/java/frc/robot/Robot.java @@ -117,6 +117,8 @@ public void robotPeriodic() { // Puts data on the elastic dashboard SmartDashboard.putString("Alliance Color", Robot.allianceColorString()); SmartDashboard.putBoolean("Hub Active?", hubActive()); + SmartDashboard.putString("Selected Action:", + robotContainer.getAutoChooser().getCommandDescription()); } // Gets the alliance color. diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index b8acae2..f97bc5e 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -155,6 +155,7 @@ public void putShuffleboardCommands() { public Command getAutonomousCommand() { return autoChooser.getCommand(); } + public RobotVisualizer getRobotVisualizer() { return robotVisualizer; } diff --git a/src/main/java/frc/robot/autochooser/AutoChooser.java b/src/main/java/frc/robot/autochooser/AutoChooser.java index 941696f..8e4e98b 100644 --- a/src/main/java/frc/robot/autochooser/AutoChooser.java +++ b/src/main/java/frc/robot/autochooser/AutoChooser.java @@ -5,8 +5,6 @@ import org.littletonrobotics.junction.networktables.LoggedDashboardChooser; -import frc.robot.utils.logging.commands.DoNothingCommand; -import frc.robot.utils.logging.commands.DoSomethingCommand; import frc.robot.utils.logging.commands.LoggableCommand; public class AutoChooser { @@ -75,6 +73,7 @@ public LoggableCommand getCommand() { return get().getCommand(); } + /** @return A human-readable description of the selected command. */ public String getCommandDescription() { return get().getDescription(); } diff --git a/src/main/java/frc/robot/autochooser/AutoCommand.java b/src/main/java/frc/robot/autochooser/AutoCommand.java index ccfc303..a53a8ab 100644 --- a/src/main/java/frc/robot/autochooser/AutoCommand.java +++ b/src/main/java/frc/robot/autochooser/AutoCommand.java @@ -4,6 +4,7 @@ import frc.robot.utils.logging.commands.DoNothingCommand; import frc.robot.utils.logging.commands.DoSomethingCommand; +/** An enum to associate commands with human-readable descriptions. */ public enum AutoCommand { // Add commands here. Importantly, you should give each command @@ -12,11 +13,11 @@ public enum AutoCommand { // drive team visual feedback on the elastic dashboard when // selecting an autonoumous command. DoNothingCommand( - "The robot will do nothing.", + "The robot won't do anything. This may happen due to an invalid selection.", new DoNothingCommand() ), DoSomethingCommand( - "This will just print something to the terminal.", + "Something will be printed to the terminal.", new DoSomethingCommand(""" SUCCESSFULLY From ae8f723ee11bd3ddd647119f0faa681d3489eb13 Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Fri, 6 Feb 2026 18:27:35 -0500 Subject: [PATCH 14/21] Got rid of unnecessary things. --- src/main/java/frc/robot/RobotContainer.java | 5 --- .../java/frc/robot/autochooser/AutoEvent.java | 34 ------------------- 2 files changed, 39 deletions(-) diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index 41a4cde..e239efd 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -17,17 +17,12 @@ import frc.robot.commands.feeder.SpinFeeder; import frc.robot.commands.drive.DriveDirectionTime; import frc.robot.commands.intake.SpinIntake; -import frc.robot.autochooser.AutoAction; import frc.robot.autochooser.AutoChooser; -import frc.robot.autochooser.FieldLocation; -import frc.robot.autochooser.AutoEvent; import frc.robot.constants.Constants; import frc.robot.subsystems.FeederSubsystem; import frc.robot.subsystems.GyroSubsystem; import frc.robot.subsystems.IntakeSubsystem; import frc.robot.subsystems.swervedrive.SwerveSubsystem; -import frc.robot.utils.logging.commands.DoNothingCommand; -import frc.robot.utils.logging.commands.DoSomethingCommand; import frc.robot.constants.Constants; import frc.robot.subsystems.GyroSubsystem; import frc.robot.utils.logging.io.gyro.RealGyroIo; diff --git a/src/main/java/frc/robot/autochooser/AutoEvent.java b/src/main/java/frc/robot/autochooser/AutoEvent.java index b7cca43..5b5ffd2 100644 --- a/src/main/java/frc/robot/autochooser/AutoEvent.java +++ b/src/main/java/frc/robot/autochooser/AutoEvent.java @@ -1,9 +1,5 @@ package frc.robot.autochooser; -import java.util.Objects; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - /** * Wrapper Class, that Contains a {@link frc.robot.autochooser.AutoAction} and a {@link * frc.robot.autochooser.FieldLocation} @@ -25,34 +21,4 @@ public FieldLocation getLocation() { return location; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AutoEvent autoEvent = (AutoEvent) o; - return action.equals(autoEvent.action) && location.equals(autoEvent.location); - } - - @Override - public int hashCode() { - return Objects.hash(action, location); - } - - @Override - public String toString() { - return "AutoEvent[action = " + action.toString() + ", location = " + location.toString() + "]"; - } - - public static AutoEvent fromString(String name) { - // Regex to capture the values inside 'action = ' and 'location = ' - Pattern pattern = Pattern.compile("AutoEvent\\[action = (.*), location = (.*)\\]"); - Matcher matcher = pattern.matcher(name); - - if (matcher.find()) { - AutoAction action = AutoAction.fromName(matcher.group(1)); - FieldLocation location = FieldLocation.fromName(matcher.group(2)); - return new AutoEvent(action, location); - } - throw new IllegalArgumentException("Invalid format"); - } } From 10475f7c9b12bbf2b395baf253ad1a3a56a597da Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Fri, 6 Feb 2026 18:40:53 -0500 Subject: [PATCH 15/21] Differentiated between 'nothing' and 'invalid' for AutoCommand, and moved more important parts of the elastic dashboard outside 'if debug'. --- src/main/java/frc/robot/Robot.java | 11 ++++++----- src/main/java/frc/robot/autochooser/AutoChooser.java | 6 +++--- src/main/java/frc/robot/autochooser/AutoCommand.java | 7 ++++--- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/main/java/frc/robot/Robot.java b/src/main/java/frc/robot/Robot.java index 65694ee..d1a4a0d 100644 --- a/src/main/java/frc/robot/Robot.java +++ b/src/main/java/frc/robot/Robot.java @@ -115,12 +115,13 @@ public void robotPeriodic() { SmartDashboard.putNumber("driverXbox.getLeftY()",driverXbox.getLeftY()); SmartDashboard.putNumber("driverXbox::getRightX", driverXbox.getRightX()); Logger.recordOutput("MyPose", robotContainer.getDriveBase().getPose()); - // Puts data on the elastic dashboard - SmartDashboard.putString("Alliance Color", Robot.allianceColorString()); - SmartDashboard.putBoolean("Hub Active?", hubActive()); - SmartDashboard.putString("Selected Action:", - robotContainer.getAutoChooser().getCommandDescription()); } + + // Puts data on the elastic dashboard + SmartDashboard.putString("Alliance Color", Robot.allianceColorString()); + SmartDashboard.putBoolean("Hub Active?", hubActive()); + SmartDashboard.putString("Selected Action:", + robotContainer.getAutoChooser().getCommandDescription()); // Gets the alliance color. if (DriverStation.isDSAttached() && allianceColor.isEmpty()) { diff --git a/src/main/java/frc/robot/autochooser/AutoChooser.java b/src/main/java/frc/robot/autochooser/AutoChooser.java index 8e4e98b..6465d28 100644 --- a/src/main/java/frc/robot/autochooser/AutoChooser.java +++ b/src/main/java/frc/robot/autochooser/AutoChooser.java @@ -16,7 +16,7 @@ public class AutoChooser { /** Structure for mapping possible choices to commands. */ private final Map commandMap = new HashMap<>(); - private final AutoCommand DEFAULT_COMMAND = AutoCommand.DoNothingCommand; + private final AutoCommand DEFAULT_COMMAND = AutoCommand.Invalid; public AutoChooser() { this.locationChooser = new LoggedDashboardChooser<>( @@ -56,9 +56,9 @@ private void populateChoosers() { private void populateMap() { // Currently, we have some example mappings. commandMap.put(new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.LEFT), - AutoCommand.DoNothingCommand); + AutoCommand.DoNothing); commandMap.put(new AutoEvent(AutoAction.DO_NOTHING, FieldLocation.RIGHT), - AutoCommand.DoSomethingCommand); + AutoCommand.DoSomething); } private AutoCommand get() { diff --git a/src/main/java/frc/robot/autochooser/AutoCommand.java b/src/main/java/frc/robot/autochooser/AutoCommand.java index a53a8ab..6d31ab4 100644 --- a/src/main/java/frc/robot/autochooser/AutoCommand.java +++ b/src/main/java/frc/robot/autochooser/AutoCommand.java @@ -12,11 +12,12 @@ public enum AutoCommand { // the robot will actually do. This will be used to give the // drive team visual feedback on the elastic dashboard when // selecting an autonoumous command. - DoNothingCommand( - "The robot won't do anything. This may happen due to an invalid selection.", + Invalid( + "The selection is invalid. (The robot won't do anything.)", new DoNothingCommand() ), - DoSomethingCommand( + DoNothing("The robot won't do anything.", new DoNothingCommand()), + DoSomething( "Something will be printed to the terminal.", new DoSomethingCommand(""" SUCCESSFULLY From 38a6ccd9e87979dbf562989c80216091d8cc3dbe Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Fri, 6 Feb 2026 18:53:11 -0500 Subject: [PATCH 16/21] Added methods for getting the location of the robot. --- src/main/java/frc/robot/Robot.java | 8 ++++++-- src/main/java/frc/robot/autochooser/AutoChooser.java | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/frc/robot/Robot.java b/src/main/java/frc/robot/Robot.java index d1a4a0d..5f493d9 100644 --- a/src/main/java/frc/robot/Robot.java +++ b/src/main/java/frc/robot/Robot.java @@ -20,6 +20,7 @@ import edu.wpi.first.wpilibj2.command.Command; import edu.wpi.first.wpilibj2.command.CommandScheduler; import edu.wpi.first.wpilibj2.command.button.CommandXboxController; +import frc.robot.autochooser.FieldLocation; import frc.robot.constants.Constants; import frc.robot.utils.logging.commands.CommandLogger; @@ -116,12 +117,13 @@ public void robotPeriodic() { SmartDashboard.putNumber("driverXbox::getRightX", driverXbox.getRightX()); Logger.recordOutput("MyPose", robotContainer.getDriveBase().getPose()); } - + // Puts data on the elastic dashboard SmartDashboard.putString("Alliance Color", Robot.allianceColorString()); SmartDashboard.putBoolean("Hub Active?", hubActive()); - SmartDashboard.putString("Selected Action:", + SmartDashboard.putString("Selected Action", robotContainer.getAutoChooser().getCommandDescription()); + SmartDashboard.putString("Starting Location", location().toString()); // Gets the alliance color. if (DriverStation.isDSAttached() && allianceColor.isEmpty()) { @@ -247,8 +249,10 @@ public static Diagnostics getDiagnostics() { return diagnostics; } + // Getters public boolean hubActive() {return hubActive;} public static Optional allianceColor() {return allianceColor;} public static String allianceColorString() {return String.valueOf(allianceColor.orElse(null));} + public FieldLocation location() {return robotContainer.getAutoChooser().getLocation();} } diff --git a/src/main/java/frc/robot/autochooser/AutoChooser.java b/src/main/java/frc/robot/autochooser/AutoChooser.java index 6465d28..877b9c6 100644 --- a/src/main/java/frc/robot/autochooser/AutoChooser.java +++ b/src/main/java/frc/robot/autochooser/AutoChooser.java @@ -78,4 +78,8 @@ public String getCommandDescription() { return get().getDescription(); } + public FieldLocation getLocation() { + return locationChooser.get(); + } + } From 3245a6cc4c3fd7d3d6c45997798ff651bdfb2f2f Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Fri, 6 Feb 2026 19:29:29 -0500 Subject: [PATCH 17/21] Cleaned indentation in RobotContainer. --- src/main/java/frc/robot/RobotContainer.java | 57 +++++++++++---------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index 52fd2cf..6f3e6fb 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -47,16 +47,16 @@ * subsystems, commands, and trigger mappings) should be declared here. */ public class RobotContainer { - private final CommandJoystick driveJoystick = new CommandJoystick(Constants.DRIVE_JOYSTICK_PORT); - private final CommandJoystick steerJoystick = new CommandJoystick(Constants.STEER_JOYSTICK_PORT); - // Instantiate the autochooser. - private final AutoChooser autoChooser = new AutoChooser(); - // The robot's subsystems and commands are defined here... + private final CommandJoystick driveJoystick = new CommandJoystick(Constants.DRIVE_JOYSTICK_PORT); + private final CommandJoystick steerJoystick = new CommandJoystick(Constants.STEER_JOYSTICK_PORT); + // Instantiate the autochooser. + private final AutoChooser autoChooser = new AutoChooser(); + // The robot's subsystems and commands are defined here... //private final TiltSubsystem tiltSubsystem; private final IntakeSubsystem intakeSubsystem; - private final FeederSubsystem feederSubsystem; + private final FeederSubsystem feederSubsystem; private RobotVisualizer robotVisualizer = null; - private final HopperSubsystem hopperSubsystem; + private final HopperSubsystem hopperSubsystem; private SwerveSubsystem drivebase = null; private GyroSubsystem gyroSubsystem = null; private ShootingState shootState = new ShootingState(ShootState.STOPPED); @@ -103,11 +103,11 @@ public RobotContainer() { default -> { throw new RuntimeException("Did not specify Robot Mode"); } - } + } configureBindings(); putShuffleboardCommands(); - - } + } + /** * Use this method to define your trigger->command mappings. Triggers can be created via the * {@link Trigger#Trigger(java.util.function.BooleanSupplier)} constructor with an arbitrary @@ -143,15 +143,15 @@ private void configureBindings() { public void putShuffleboardCommands() { if (Constants.DEBUG) { - /*SmartDashboard.putData( + /*SmartDashboard.putData( "Spin Roller", new SpinRoller(rollerSubsystem)); - SmartDashboard.putData( + SmartDashboard.putData( "Tilt Up", new TiltUp(tiltSubsystem)); - SmartDashboard.putData( + SmartDashboard.putData( "Tilt Down", new TiltDown(tiltSubsystem));*/ @@ -197,29 +197,30 @@ public void putShuffleboardCommands() { new SetShootingState(shootState, ShootState.SHUTTLING)); } + //basic drive command - if(!Constants.TESTBED){ + if(!Constants.TESTBED) { Command driveDirectionTime = new DriveDirectionTime(drivebase, 0.1,0.1, true, 1); SmartDashboard.putData("Drive Command", driveDirectionTime); } } - /** - * Use this to pass the autonomous command to the main {@link Robot} class. - * - * @return the command to run in autonomous - */ - public Command getAutonomousCommand() { - return autoChooser.getCommand(); - } + /** + * Use this to pass the autonomous command to the main {@link Robot} class. + * + * @return the command to run in autonomous + */ + public Command getAutonomousCommand() { + return autoChooser.getCommand(); + } - public RobotVisualizer getRobotVisualizer() { - return robotVisualizer; - } + public RobotVisualizer getRobotVisualizer() { + return robotVisualizer; + } - public AutoChooser getAutoChooser() { - return autoChooser; - } + public AutoChooser getAutoChooser() { + return autoChooser; + } public IntakeSubsystem getIntakeSubsystem() { return intakeSubsystem; From 5bbec3dee288676207041bee3a9bc670fc864549 Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Fri, 6 Feb 2026 20:53:48 -0500 Subject: [PATCH 18/21] I cleaned up unnecessary changes to RobotContainer, some small whitespace changes may remain. --- src/main/java/frc/robot/RobotContainer.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index 6f3e6fb..4d2169b 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -47,8 +47,6 @@ * subsystems, commands, and trigger mappings) should be declared here. */ public class RobotContainer { - private final CommandJoystick driveJoystick = new CommandJoystick(Constants.DRIVE_JOYSTICK_PORT); - private final CommandJoystick steerJoystick = new CommandJoystick(Constants.STEER_JOYSTICK_PORT); // Instantiate the autochooser. private final AutoChooser autoChooser = new AutoChooser(); // The robot's subsystems and commands are defined here... @@ -59,8 +57,11 @@ public class RobotContainer { private final HopperSubsystem hopperSubsystem; private SwerveSubsystem drivebase = null; private GyroSubsystem gyroSubsystem = null; + private final CommandJoystick driveJoystick = new CommandJoystick(Constants.DRIVE_JOYSTICK_PORT); + private final CommandJoystick steerJoystick = new CommandJoystick(Constants.STEER_JOYSTICK_PORT); private ShootingState shootState = new ShootingState(ShootState.STOPPED); + // Replace with CommandPS4Controller or CommandJoystick if needed //new CommandXboxController(OperatorConstants.kDriverControllerPort);private final CommandXboxController controller = new CommandXboxController(Constants.XBOX_CONTROLLER_PORT); /** @@ -70,6 +71,8 @@ public RobotContainer() { // Configure the trigger bindings switch (Constants.currentMode) { case REAL -> { + //rollerSubsystem = new RollerSubsystem(RollerSubsystem.createRealIo()); + //rollerSubsystem = new RollerSubsystem(RollerSubsystem.createRealIo()); intakeSubsystem = new IntakeSubsystem(IntakeSubsystem.createRealIo(), IntakeSubsystem.createRealDeploymentSwitch()); hopperSubsystem = new HopperSubsystem(HopperSubsystem.createRealIo()); @@ -83,6 +86,8 @@ public RobotContainer() { drivebase = !Constants.TESTBED ? new SwerveSubsystem(new File(Filesystem.getDeployDirectory(), "YAGSL"), swerveIMU) : null; } case REPLAY -> { + //rollerSubsystem = new RollerSubsystem(RollerSubsystem.createMockIo()); + //tiltSubsystem = new TiltSubsystem(TiltSubsystem.createMockIo()); intakeSubsystem = new IntakeSubsystem(IntakeSubsystem.createMockIo(), IntakeSubsystem.createMockDeploymentSwitch()); hopperSubsystem = new HopperSubsystem(HopperSubsystem.createMockIo()); feederSubsystem = new FeederSubsystem(FeederSubsystem.createMockIo()); @@ -91,6 +96,8 @@ public RobotContainer() { drivebase = !Constants.TESTBED ? new SwerveSubsystem(new File(Filesystem.getDeployDirectory(), "YAGSL"), null) : null; } case SIM -> { + //rollerSubsystem = new RollerSubsystem(RollerSubsystem.createSimIo(robotVisualizer)); + //tiltSubsystem = new TiltSubsystem(TiltSubsystem.createSimIo(robotVisualizer)); robotVisualizer = new RobotVisualizer(); intakeSubsystem = new IntakeSubsystem(IntakeSubsystem.createSimIo(robotVisualizer), IntakeSubsystem.createSimDeploymentSwitch()); hopperSubsystem = new HopperSubsystem(HopperSubsystem.createSimIo(robotVisualizer)); @@ -213,7 +220,7 @@ public void putShuffleboardCommands() { public Command getAutonomousCommand() { return autoChooser.getCommand(); } - + public RobotVisualizer getRobotVisualizer() { return robotVisualizer; } From b7e1e32c5037d46f063b805e0b69ce66dcec0327 Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Mon, 9 Feb 2026 18:57:47 -0500 Subject: [PATCH 19/21] Clean up merge. --- src/main/java/frc/robot/RobotContainer.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index 021836c..5b321e9 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -35,8 +35,6 @@ //import frc.robot.subsystems.RollerSubsystem; //import frc.robot.subsystems.TiltSubsystem; import frc.robot.subsystems.swervedrive.SwerveSubsystem; -import frc.robot.constants.Constants; -import frc.robot.subsystems.GyroSubsystem; import frc.robot.utils.logging.io.gyro.RealGyroIo; import frc.robot.utils.logging.io.gyro.ThreadedGyro; import frc.robot.utils.logging.io.gyro.ThreadedGyroSwerveIMU; @@ -113,9 +111,9 @@ public RobotContainer() { drivebase = !Constants.TESTBED ? new SwerveSubsystem(new File(Filesystem.getDeployDirectory(), "YAGSL"), null) : null; } case SIM -> { + robotVisualizer = new RobotVisualizer(); //rollerSubsystem = new RollerSubsystem(RollerSubsystem.createSimIo(robotVisualizer)); //tiltSubsystem = new TiltSubsystem(TiltSubsystem.createSimIo(robotVisualizer)); - robotVisualizer = new RobotVisualizer(); anglerSubsystem = new AnglerSubsystem(AnglerSubsystem.createSimIo(robotVisualizer)); intakeSubsystem = new IntakeSubsystem(IntakeSubsystem.createSimIo(robotVisualizer), IntakeSubsystem.createSimDeploymentSwitch()); hopperSubsystem = new HopperSubsystem(HopperSubsystem.createSimIo(robotVisualizer)); From 7bb6c911420cbe5a641f67a74be4369f21e1c88c Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Mon, 9 Feb 2026 19:18:15 -0500 Subject: [PATCH 20/21] Made a getter for the starting position. --- src/main/java/frc/robot/Robot.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/frc/robot/Robot.java b/src/main/java/frc/robot/Robot.java index e65f581..ce87288 100644 --- a/src/main/java/frc/robot/Robot.java +++ b/src/main/java/frc/robot/Robot.java @@ -14,6 +14,8 @@ import org.littletonrobotics.junction.networktables.NT4Publisher; import org.littletonrobotics.junction.wpilog.WPILOGReader; import org.littletonrobotics.junction.wpilog.WPILOGWriter; + +import edu.wpi.first.math.geometry.Pose2d; import edu.wpi.first.wpilibj.DriverStation; import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; import edu.wpi.first.wpilibj.DriverStation.Alliance; @@ -260,5 +262,6 @@ public static Diagnostics getDiagnostics() { public static Optional allianceColor() {return allianceColor;} public static String allianceColorString() {return String.valueOf(allianceColor.orElse(null));} public FieldLocation location() {return robotContainer.getAutoChooser().getLocation();} + public Pose2d getStartingLocation() {return location().getLocation();} } From 09f4f94241ea1731dc4563780264b0eadf8fbd93 Mon Sep 17 00:00:00 2001 From: Raayed Mohammed Date: Mon, 9 Feb 2026 20:42:33 -0500 Subject: [PATCH 21/21] Reimplemented equals() ans hashCode() so that the AutoEvent class can be used in a map the way it's expected to. --- src/main/java/frc/robot/RobotContainer.java | 2 +- .../java/frc/robot/autochooser/AutoEvent.java | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index 5b321e9..840aef0 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -25,8 +25,8 @@ import frc.robot.commands.shooter.SetShootingState; import frc.robot.constants.Constants; import frc.robot.subsystems.AnglerSubsystem; -import frc.robot.subsystems.HopperSubsystem; import frc.robot.subsystems.ApriltagSubsystem; +import frc.robot.subsystems.HopperSubsystem; import frc.robot.subsystems.FeederSubsystem; import frc.robot.constants.ShootingState; import frc.robot.constants.ShootingState.ShootState; diff --git a/src/main/java/frc/robot/autochooser/AutoEvent.java b/src/main/java/frc/robot/autochooser/AutoEvent.java index 5b5ffd2..38e4fef 100644 --- a/src/main/java/frc/robot/autochooser/AutoEvent.java +++ b/src/main/java/frc/robot/autochooser/AutoEvent.java @@ -21,4 +21,31 @@ public FieldLocation getLocation() { return location; } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((action == null) ? 0 : action.hashCode()); + result = prime * result + ((location == null) ? 0 : location.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AutoEvent other = (AutoEvent) obj; + if (action != other.action) + return false; + if (location != other.location) + return false; + return true; + } + + + }