diff --git a/src/main/java/frc/robot/Constants.java b/src/main/java/frc/robot/Constants.java index 63ce8c3..63fffc5 100644 --- a/src/main/java/frc/robot/Constants.java +++ b/src/main/java/frc/robot/Constants.java @@ -10,7 +10,6 @@ import edu.wpi.first.math.Pair; import edu.wpi.first.math.geometry.Pose2d; import edu.wpi.first.math.util.Units; -import edu.wpi.first.wpilibj.util.Color8Bit; import frc.robot.commands.AlignToReef.ReefBranch; import java.util.HashMap; import java.util.Map; @@ -113,21 +112,4 @@ public static class VisionConstants { /** The rotational tolerance value for aligning to the reef. */ public static final double REEF_ALIGNMENT_TOLERANCE_R = 1.0; // in deg } - - public static class ColorConstants { - public static final Color8Bit BLACK = new Color8Bit(0, 0, 0); - public static final Color8Bit WHITE = new Color8Bit(200, 200, 200); - public static final Color8Bit RED = new Color8Bit(255, 0, 0); - public static final Color8Bit ORANGE = new Color8Bit(255, 119, 0); - public static final Color8Bit YELLOW = new Color8Bit(255, 165, 0); - public static final Color8Bit GREEN = new Color8Bit(0, 204, 0); - public static final Color8Bit BLUE = new Color8Bit(0, 0, 204); - public static final Color8Bit PURPLE = new Color8Bit(238, 80, 255); - public static final Color8Bit PINK = new Color8Bit(255, 5, 100); - public static final Color8Bit LIGHTBLUE = new Color8Bit(56, 197, 252); - - public static final Color8Bit COLORS[] = { - BLACK, WHITE, RED, ORANGE, YELLOW, GREEN, BLUE, LIGHTBLUE, PURPLE, PINK, - }; - } } diff --git a/src/main/java/frc/robot/commands/BlinkColor.java b/src/main/java/frc/robot/commands/BlinkColor.java index 0d13223..b98bc22 100644 --- a/src/main/java/frc/robot/commands/BlinkColor.java +++ b/src/main/java/frc/robot/commands/BlinkColor.java @@ -7,28 +7,31 @@ package frc.robot.commands; +import static frc.robot.parameters.Colors.BLACK; + import edu.wpi.first.wpilibj.Timer; -import edu.wpi.first.wpilibj.util.Color8Bit; import edu.wpi.first.wpilibj2.command.Command; -import frc.robot.Constants; +import frc.robot.parameters.Colors; import frc.robot.subsystems.LEDSubsystem; -/** A command to blink the status LEDs green. */ -public class BlinkColor extends Command { +/** A command to blink the status LEDs a specified color. */ +public final class BlinkColor extends Command { private static final double BLINK_TIME = 0.2; private final LEDSubsystem led; - private final Color8Bit color; + private final Colors color; private final double duration; private final Timer timer = new Timer(); private boolean isOn; /** Creates a new BlinkColor. */ - public BlinkColor(LEDSubsystem led, Color8Bit color, double duration) { - // Use addRequirements() here to declare subsystem dependencies. + public BlinkColor(LEDSubsystem led, Colors color, double duration) { + setName(String.format("BlinkColor(%s)", color.name())); + this.led = led; this.color = color; this.duration = duration; + addRequirements(led); } @@ -47,7 +50,7 @@ public void execute() { if (timer.advanceIfElapsed(BLINK_TIME)) { if (isOn) { - led.fillAndCommitColor(Constants.ColorConstants.BLACK); + led.fillAndCommitColor(BLACK); } else { led.fillAndCommitColor(color); } diff --git a/src/main/java/frc/robot/commands/DriveCommands.java b/src/main/java/frc/robot/commands/DriveCommands.java index b539b39..78b2ce8 100644 --- a/src/main/java/frc/robot/commands/DriveCommands.java +++ b/src/main/java/frc/robot/commands/DriveCommands.java @@ -7,6 +7,8 @@ package frc.robot.commands; +import static frc.robot.parameters.Colors.WHITE; + import com.pathplanner.lib.auto.AutoBuilder; import com.pathplanner.lib.path.PathConstraints; import edu.wpi.first.apriltag.AprilTagFieldLayout; @@ -20,7 +22,6 @@ import edu.wpi.first.wpilibj2.command.Command; import edu.wpi.first.wpilibj2.command.Commands; import frc.robot.Constants; -import frc.robot.Constants.ColorConstants; import frc.robot.commands.AlignToReef.ReefBranch; import frc.robot.parameters.SwerveDriveParameters; import frc.robot.subsystems.Subsystems; @@ -49,7 +50,7 @@ public static Command resetOrientation(Subsystems subsystems) { public static Command alignToBranch(Subsystems subsystems, ReefBranch branch) { return Commands.sequence( new AlignToReef(subsystems, branch), - new BlinkColor(subsystems.statusLEDs, ColorConstants.WHITE, 1).repeatedly()) + new BlinkColor(subsystems.statusLEDs, WHITE, 1).repeatedly()) .withName(String.format("AlignToReef(%s)", branch.name())); } diff --git a/src/main/java/frc/robot/commands/FlameCycle.java b/src/main/java/frc/robot/commands/FlameCycle.java index ea0a987..0ea4aba 100644 --- a/src/main/java/frc/robot/commands/FlameCycle.java +++ b/src/main/java/frc/robot/commands/FlameCycle.java @@ -7,18 +7,21 @@ package frc.robot.commands; +import static frc.robot.parameters.Colors.BLACK; +import static frc.robot.parameters.Colors.RED; +import static frc.robot.parameters.Colors.YELLOW; + import edu.wpi.first.wpilibj.util.Color8Bit; import edu.wpi.first.wpilibj2.command.Command; -import frc.robot.Constants.ColorConstants; -import frc.robot.Constants.RobotConstants; import frc.robot.subsystems.StatusLED; /** A command to display an animated flame pattern on the status LEDs. */ -public class FlameCycle extends Command { +public final class FlameCycle extends Command { private final StatusLED led; - private final int redDiff = ColorConstants.RED.red - ColorConstants.YELLOW.red; - private final int greenDiff = ColorConstants.RED.green - ColorConstants.YELLOW.green; - private final int blueDiff = ColorConstants.RED.blue - ColorConstants.YELLOW.blue; + private final int ledCount; + private final int redDiff = RED.getRed() - YELLOW.getRed(); + private final int greenDiff = RED.getGreen() - YELLOW.getGreen(); + private final int blueDiff = RED.getBlue() - YELLOW.getBlue(); private int step; @@ -26,6 +29,7 @@ public class FlameCycle extends Command { public FlameCycle(StatusLED led) { // Use addRequirements() here to declare subsystem dependencies. this.led = led; + this.ledCount = led.getLEDCount(); addRequirements(led); } @@ -33,7 +37,7 @@ public FlameCycle(StatusLED led) { @Override public void initialize() { step = 0; - led.fillColor(ColorConstants.BLACK); + led.fillColor(BLACK); led.commitColor(); } @@ -43,15 +47,15 @@ public void execute() { double multiplier = Math.sin(step++ * Math.toRadians(6)) * 0.5 + .5; Color8Bit color0 = new Color8Bit( - (int) (-(redDiff * multiplier) + ColorConstants.RED.red), - (int) (-(greenDiff * multiplier) + ColorConstants.RED.green), - (int) (-(blueDiff * multiplier) + ColorConstants.RED.blue)); + (int) (-(redDiff * multiplier) + RED.getRed()), + (int) (-(greenDiff * multiplier) + RED.getGreen()), + (int) (-(blueDiff * multiplier) + RED.getBlue())); Color8Bit color1 = new Color8Bit( - (int) (redDiff * multiplier + ColorConstants.YELLOW.red), - (int) (greenDiff * multiplier + ColorConstants.YELLOW.green), - (int) (blueDiff * multiplier + ColorConstants.YELLOW.blue)); - for (int i = 0; i < RobotConstants.LED_COUNT; i++) { + (int) (redDiff * multiplier + YELLOW.getRed()), + (int) (greenDiff * multiplier + YELLOW.getGreen()), + (int) (blueDiff * multiplier + YELLOW.getBlue())); + for (int i = 0; i < ledCount; i++) { Color8Bit color = ((i / 3) % 2) == 0 ? color0 : color1; led.setColor(color, i); } diff --git a/src/main/java/frc/robot/commands/LEDCommands.java b/src/main/java/frc/robot/commands/LEDCommands.java index 3401ed8..254983b 100644 --- a/src/main/java/frc/robot/commands/LEDCommands.java +++ b/src/main/java/frc/robot/commands/LEDCommands.java @@ -7,10 +7,11 @@ package frc.robot.commands; -import edu.wpi.first.wpilibj.util.Color8Bit; +import static frc.robot.parameters.Colors.GREEN; + import edu.wpi.first.wpilibj2.command.Command; import edu.wpi.first.wpilibj2.command.Commands; -import frc.robot.Constants.ColorConstants; +import frc.robot.parameters.Colors; import frc.robot.subsystems.StatusLED; import frc.robot.subsystems.Subsystems; @@ -25,9 +26,9 @@ public final class LEDCommands { * @param color The color to set. * @return A command that sets the color of the status LED. */ - public static Command setColor(StatusLED statusLED, Color8Bit color) { + public static Command setColor(StatusLED statusLED, Colors color) { return Commands.runOnce(() -> statusLED.fillAndCommitColor(color), statusLED) - .withName("SetColor"); + .withName(String.format("SetColor(%s)", color.name())); } /** @@ -40,8 +41,8 @@ public static Command setColor(StatusLED statusLED, Color8Bit color) { */ public static Command indicateCoralAcquired(Subsystems subsystem) { return Commands.sequence( - new BlinkColor(subsystem.statusLEDs, ColorConstants.GREEN, BLINK_DURATION), - setColor(subsystem.statusLEDs, ColorConstants.GREEN), + new BlinkColor(subsystem.statusLEDs, GREEN, BLINK_DURATION), + setColor(subsystem.statusLEDs, GREEN), Commands.idle(subsystem.statusLEDs).until(() -> !subsystem.coralRoller.hasCoral())) .withName("IndicateCoralAcquired"); } @@ -56,8 +57,8 @@ public static Command indicateCoralAcquired(Subsystems subsystem) { */ public static Command indicateAlgaeAcquired(Subsystems subsystem) { return Commands.sequence( - new BlinkColor(subsystem.statusLEDs, ColorConstants.GREEN, BLINK_DURATION), - setColor(subsystem.statusLEDs, ColorConstants.GREEN), + new BlinkColor(subsystem.statusLEDs, GREEN, BLINK_DURATION), + setColor(subsystem.statusLEDs, GREEN), Commands.idle(subsystem.statusLEDs).until(() -> !subsystem.algaeGrabber.hasAlgae())) .withName("IndicateAlgaeAcquired"); } diff --git a/src/main/java/frc/robot/commands/RainbowCycle.java b/src/main/java/frc/robot/commands/RainbowCycle.java index d252e97..e9b64c2 100644 --- a/src/main/java/frc/robot/commands/RainbowCycle.java +++ b/src/main/java/frc/robot/commands/RainbowCycle.java @@ -7,22 +7,24 @@ package frc.robot.commands; +import static frc.robot.parameters.Colors.BLACK; + import edu.wpi.first.wpilibj.util.Color; import edu.wpi.first.wpilibj.util.Color8Bit; import edu.wpi.first.wpilibj2.command.Command; -import frc.robot.Constants.ColorConstants; -import frc.robot.Constants.RobotConstants; import frc.robot.subsystems.StatusLED; /** A command to display an animated rainbow cycle pattern on the status LEDs. */ -public class RainbowCycle extends Command { +public final class RainbowCycle extends Command { private final StatusLED led; + private final int ledCount; private int step; /** Creates a new RainbowCycle. */ public RainbowCycle(StatusLED led) { // Use addRequirements() here to declare subsystem dependencies. this.led = led; + this.ledCount = led.getLEDCount(); addRequirements(led); } @@ -30,7 +32,7 @@ public RainbowCycle(StatusLED led) { @Override public void initialize() { step = 0; - led.fillColor(ColorConstants.BLACK); + led.fillColor(BLACK); led.commitColor(); } @@ -38,7 +40,7 @@ public void initialize() { @Override public void execute() { int firstPixelHue = step++ * 3; - for (int i = 0; i < RobotConstants.LED_COUNT; i++) { + for (int i = 0; i < ledCount; i++) { Color8Bit color = new Color8Bit(Color.fromHSV((firstPixelHue + ((180 * (i + 1)) / 21)) % 180, 255, 255)); led.setColor(color, i); diff --git a/src/main/java/frc/robot/parameters/Colors.java b/src/main/java/frc/robot/parameters/Colors.java new file mode 100644 index 0000000..d9b849d --- /dev/null +++ b/src/main/java/frc/robot/parameters/Colors.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2025 Newport Robotics Group. All Rights Reserved. + * + * Open Source Software; you can modify and/or share it under the terms of + * the license file in the root directory of this project. + */ + +package frc.robot.parameters; + +import edu.wpi.first.wpilibj.util.Color8Bit; + +/** An enum representing common RGB colors used with the status LEDs. */ +public enum Colors { + BLACK(0, 0, 0), + WHITE(200, 200, 200), + RED(255, 0, 0), + ORANGE(255, 119, 0), + YELLOW(255, 165, 0), + GREEN(0, 204, 0), + BLUE(0, 0, 204), + PURPLE(238, 80, 255), + PINK(255, 5, 100), + LIGHT_BLUE(56, 197, 252); + + private final Color8Bit color; + + /** Constructs a variant of this enum. */ + Colors(int red, int green, int blue) { + color = new Color8Bit(red, green, blue); + } + + /** Returns the red component of this enum variant. */ + public int getRed() { + return color.red; + } + + /** Returns the green component of this enum variant. */ + public int getGreen() { + return color.green; + } + + /** Returns the blue component of this enum variant. */ + public int getBlue() { + return color.blue; + } + + /** Returns the color of this enum variant. */ + public Color8Bit getColor() { + return color; + } +} diff --git a/src/main/java/frc/robot/subsystems/LEDSubsystem.java b/src/main/java/frc/robot/subsystems/LEDSubsystem.java index 5e46918..fec12e1 100644 --- a/src/main/java/frc/robot/subsystems/LEDSubsystem.java +++ b/src/main/java/frc/robot/subsystems/LEDSubsystem.java @@ -9,34 +9,95 @@ import edu.wpi.first.wpilibj.util.Color8Bit; import edu.wpi.first.wpilibj2.command.SubsystemBase; +import frc.robot.parameters.Colors; import frc.robot.util.LEDSegment; public class LEDSubsystem extends SubsystemBase { /** Creates a new LEDSubsystem. */ protected final LEDSegment leds; - // TODO: update constructor + /** + * Creates a new LEDSubsystem. + * + * @param firstLED The first LED index. + * @param ledCount The number of LEDs in the segment. + */ public LEDSubsystem(int firstLED, int ledCount) { leds = new LEDSegment(firstLED, ledCount); } + /** + * Gets the number of LEDs in the segment. + * + * @return The number of LEDs in the segment. + */ + public int getLEDCount() { + return leds.getLEDCount(); + } + + /** + * Sets the color of the LED at the specified index. + * + * @param color The color to set the LED to. + * @param index The index of the LED to set. + */ + public void setColor(Colors color, int index) { + leds.setColor(color, index); + } + + /** + * Sets the color of the LED at the specified index. + * + * @param color The color to set the LED to. + * @param index The index of the LED to set. + */ public void setColor(Color8Bit color, int index) { leds.setColor(color, index); } + /** + * Fills the segment with the specified color. + * + * @param color The color to fill the segment with. + */ + public void fillColor(Colors color) { + leds.fill(color.getColor()); + } + + /** + * Fills the segment with the specified color. + * + * @param color The color to fill the segment with. + */ + public void fillColor(Color8Bit color) { + leds.fill(color); + } + + /** + * Fills the segment with the specified color and displays it to the LED segment. + * + * @param color The color to fill the segment with. + */ + public void fillAndCommitColor(Colors color) { + leds.fill(color.getColor()); + commitColor(); + } + + /** + * Fills the segment with the specified color and displays it to the LED segment. + * + * @param color The color to fill the segment with. + */ public void fillAndCommitColor(Color8Bit color) { leds.fill(color); commitColor(); } + /** Displays the current color data on the LED strip. */ public void commitColor() { leds.commitColor(); } - public void fillColor(Color8Bit color) { - leds.fill(color); - } - @Override public void periodic() { // This method will be called once per scheduler run diff --git a/src/main/java/frc/robot/subsystems/StatusLED.java b/src/main/java/frc/robot/subsystems/StatusLED.java index 45d2b06..f7dc35c 100644 --- a/src/main/java/frc/robot/subsystems/StatusLED.java +++ b/src/main/java/frc/robot/subsystems/StatusLED.java @@ -7,11 +7,12 @@ package frc.robot.subsystems; -import static frc.robot.Constants.ColorConstants.RED; import static frc.robot.Constants.RobotConstants.LEDSegment.STATUS_FIRST_LED; import static frc.robot.Constants.RobotConstants.LEDSegment.STATUS_LED_COUNT; +import static frc.robot.parameters.Colors.RED; -public class StatusLED extends LEDSubsystem { +/** A subsystem to control the status LEDs. */ +public final class StatusLED extends LEDSubsystem { /** Creates a new StatusLEDSubsystem. */ public StatusLED() { super(STATUS_FIRST_LED, STATUS_LED_COUNT); @@ -22,6 +23,5 @@ public StatusLED() { @Override public void periodic() { // This method will be called once per scheduler run - } } diff --git a/src/main/java/frc/robot/util/LEDSegment.java b/src/main/java/frc/robot/util/LEDSegment.java index 5bc5f90..49231c8 100644 --- a/src/main/java/frc/robot/util/LEDSegment.java +++ b/src/main/java/frc/robot/util/LEDSegment.java @@ -11,13 +11,20 @@ import edu.wpi.first.wpilibj.AddressableLEDBuffer; import edu.wpi.first.wpilibj.util.Color8Bit; import frc.robot.Constants.RobotConstants; +import frc.robot.parameters.Colors; -/** Add your docs here. */ -public class LEDSegment { - - private final int firstLED; - private final int ledCount; +/** A class representing a subsegment of an LED strip. */ +public final class LEDSegment { + /** + * Gamma Correction Table + * + *
Because humans do not perceive brightness linearly, this table is used to adjust the RGB + * color data output to the LEDs. It results in improved color perception. + * + *
See the article at https://www.cambridgeincolour.com/tutorials/gamma-correction.htm for more + * information. + */ public static final int GAMMA_TABLE[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, @@ -41,6 +48,10 @@ public class LEDSegment { new AddressableLEDBuffer(RobotConstants.LED_COUNT); private static final AddressableLED leds = createAddressableLED(ledBuffer); + private final int firstLED; + private final int ledCount; + + /** Creates and initializes the shared {@link AddressableLED} object. */ private static AddressableLED createAddressableLED(AddressableLEDBuffer buffer) { AddressableLED led = new AddressableLED(RobotConstants.PWMPort.LED); led.setLength(RobotConstants.LED_COUNT); @@ -49,23 +60,69 @@ private static AddressableLED createAddressableLED(AddressableLEDBuffer buffer) return led; } + /** + * Creates a new LEDSegment. + * + * @param firstLED the index of the first LED in the segment + * @param ledCount the number of LEDs in the segment + */ public LEDSegment(int firstLED, int ledCount) { this.firstLED = firstLED; this.ledCount = ledCount; } + /** + * Gets the number of LEDs in the segment. + * + * @return The number of LEDs in the segment. + */ + public int getLEDCount() { + return ledCount; + } + + /** + * Fills the segment with the specified color. + * + * @param color The color to fill the segment with. + */ + public void fill(Colors color) { + fill(color.getColor()); + } + + /** + * Fills the segment with the specified color. + * + * @param color The color to fill the segment with. + */ public void fill(Color8Bit color) { for (int i = 0; i < ledCount; i++) { setColor(color, i + firstLED); } } - public void commitColor() { - leds.setData(ledBuffer); + /** + * Sets the color of the specified LED. + * + * @param color The color to set the LED to. + * @param index The index of the LED to set. + */ + public void setColor(Colors color, int index) { + setColor(color.getColor(), index); } + /** + * Sets the color of the specified LED. + * + * @param color The color to set the LED to. + * @param index The index of the LED to set. + */ public void setColor(Color8Bit color, int index) { ledBuffer.setRGB( index, GAMMA_TABLE[color.red], GAMMA_TABLE[color.green], GAMMA_TABLE[color.blue]); } + + /** Displays the current color data on the LED strip. */ + public void commitColor() { + leds.setData(ledBuffer); + } }