diff --git a/build.gradle b/build.gradle index c216213..18c096f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id "java" - id "edu.wpi.first.GradleRIO" version "2020.2.2" + id "edu.wpi.first.GradleRIO" version "2020.3.2" } sourceCompatibility = JavaVersion.VERSION_11 diff --git a/src/main/deploy/images/THfade.png b/src/main/deploy/images/THfade.png new file mode 100644 index 0000000..6eea347 Binary files /dev/null and b/src/main/deploy/images/THfade.png differ diff --git a/src/main/deploy/images/burst.bmp b/src/main/deploy/images/burst.bmp new file mode 100644 index 0000000..5414a88 Binary files /dev/null and b/src/main/deploy/images/burst.bmp differ diff --git a/src/main/deploy/images/fade.png b/src/main/deploy/images/fade.png new file mode 100644 index 0000000..66e4b73 Binary files /dev/null and b/src/main/deploy/images/fade.png differ diff --git a/src/main/deploy/images/noise.png b/src/main/deploy/images/noise.png new file mode 100644 index 0000000..cce17b9 Binary files /dev/null and b/src/main/deploy/images/noise.png differ diff --git a/src/main/deploy/images/noisy-pulse.png b/src/main/deploy/images/noisy-pulse.png new file mode 100644 index 0000000..1b0b1da Binary files /dev/null and b/src/main/deploy/images/noisy-pulse.png differ diff --git a/src/main/deploy/images/pulse-down.png b/src/main/deploy/images/pulse-down.png new file mode 100644 index 0000000..225c13e Binary files /dev/null and b/src/main/deploy/images/pulse-down.png differ diff --git a/src/main/deploy/images/pulse.png b/src/main/deploy/images/pulse.png new file mode 100644 index 0000000..51c1d7b Binary files /dev/null and b/src/main/deploy/images/pulse.png differ diff --git a/src/main/deploy/images/stripe.png b/src/main/deploy/images/stripe.png new file mode 100644 index 0000000..1de8523 Binary files /dev/null and b/src/main/deploy/images/stripe.png differ diff --git a/src/main/deploy/images/stripes.png b/src/main/deploy/images/stripes.png new file mode 100644 index 0000000..05f427c Binary files /dev/null and b/src/main/deploy/images/stripes.png differ diff --git a/src/main/java/frc/robot/command_groups/LEDDemoCG.java b/src/main/java/frc/robot/command_groups/LEDDemoCG.java new file mode 100644 index 0000000..b5e24b9 --- /dev/null +++ b/src/main/java/frc/robot/command_groups/LEDDemoCG.java @@ -0,0 +1,48 @@ +package frc.robot.command_groups; + +import edu.wpi.first.wpilibj.Filesystem; +import edu.wpi.first.wpilibj.command.CommandGroup; +import edu.wpi.first.wpilibj.command.WaitCommand; +import frc.robot.status.actions.ImageAction; +import frc.robot.status.actions.LedAction; +import frc.robot.status.commands.ActionCommand; +import java.io.File; + +public class LEDDemoCG extends CommandGroup { + + public LEDDemoCG() { + File deployDir = Filesystem.getDeployDirectory(); + String pathPrefix = deployDir.getAbsolutePath() + "/images/"; + + ImageAction ia = new ImageAction(pathPrefix + "THfade.png").oscillate(); + addSequential(new ActionCommand(ia)); + addSequential(new WaitCommand(10)); + + ia = new ImageAction(pathPrefix + "noise.png"); + addSequential(new ActionCommand(ia)); + addSequential(new WaitCommand(10)); + + ia = new ImageAction(pathPrefix + "noisy-pulse.png"); + addSequential(new ActionCommand(ia)); + addSequential(new WaitCommand(10)); + + ia = new ImageAction(pathPrefix + "pulse.png").oscillate(); + addSequential(new ActionCommand(ia)); + addSequential(new WaitCommand(10)); + + ia = new ImageAction(pathPrefix + "pulse-down.png").oscillate(); + addSequential(new ActionCommand(ia)); + addSequential(new WaitCommand(10)); + + ia = new ImageAction(pathPrefix + "stripes.png").oscillate(); + addSequential(new ActionCommand(ia)); + addSequential(new WaitCommand(10)); + + ia = new ImageAction(pathPrefix + "fade.png").oscillate(); + addSequential(new ActionCommand(ia)); + addSequential(new WaitCommand(10)); + + addSequential(new ActionCommand(new LedAction(0, 0, 0, 0))); + } + +} \ No newline at end of file diff --git a/src/main/java/frc/robot/status/Status.java b/src/main/java/frc/robot/status/Status.java index 4c60eab..5e02867 100644 --- a/src/main/java/frc/robot/status/Status.java +++ b/src/main/java/frc/robot/status/Status.java @@ -7,15 +7,24 @@ package frc.robot.status; +import java.io.File; + import edu.wpi.first.wpilibj.AddressableLED; import edu.wpi.first.wpilibj.AddressableLEDBuffer; import edu.wpi.first.wpilibj.DigitalOutput; +import edu.wpi.first.wpilibj.Filesystem; import edu.wpi.first.wpilibj.Timer; import edu.wpi.first.wpilibj.command.CommandGroup; import edu.wpi.first.wpilibj.command.Scheduler; import edu.wpi.first.wpilibj.command.Subsystem; import edu.wpi.first.wpilibj.command.WaitCommand; import edu.wpi.first.wpilibj.util.Color; +import frc.robot.status.actions.Action; +import frc.robot.status.actions.ChaseAction; +import frc.robot.status.actions.ImageAction; +import frc.robot.status.actions.LedAction; +import frc.robot.status.actions.PowerUpAction; +import frc.robot.status.actions.ScannerAction; import frc.robot.status.commands.ActionCommand; // @@ -48,10 +57,11 @@ public class Status extends Subsystem { private Action currentAction = null; // Object used for locking operations around the currentAction - private Object actionLock = new Object(); + private final Object actionLock = new Object(); - // Timer allows us to do things at specific game time. + // Timer tracks the delay between intervals/frames. private Timer timer = null; + private double currentDelay = 0; // If both are false then the RIO is running but neither init has triggered // (it's in boot up). @@ -91,16 +101,18 @@ private Status() { } // This will set/send the buffer to the LEDs. - public synchronized void setLedData(AddressableLEDBuffer buffer) { + public synchronized void setLedData(final AddressableLEDBuffer buffer) { addressableLed.setData(buffer); } - public void setAction(Action action) { + public void setAction(final Action action) { // Before doing anything with an action synchornize around it. // This prevents swapping the action while the action runner thread is doing // something with it. synchronized (actionLock) { currentAction = action; + action.reset(); + currentDelay = 0; // Run the first time } } @@ -108,14 +120,16 @@ public void setAction(Action action) { // Note: these can't be commands since commands require enablement. private void scheduleBootActions() { - ScannerAction scannerAction = new ScannerAction(245, 0, 255, 90); + final ScannerAction scannerAction = new ScannerAction(245, 0, 255, 90); scannerAction.setIntervalTime(0.075); - scannerAction.setIntervalCount(ADDRESSABLE_LED_COUNT * 5 * 2); // number of lights, how many times to update them, back and fourth + scannerAction.setIntervalCount(ADDRESSABLE_LED_COUNT * 5 * 2); // number of lights, how many times to update + // them, back and fourth setAction(scannerAction); - ChaseAction chaseAction = new ChaseAction(245, 0, 255, 90); - chaseAction.setIntervalCount(-1); - //setAction(chaseAction); + /* + * ChaseAction chaseAction = new ChaseAction(245, 0, 255, 90); + * chaseAction.setIntervalCount(-1); setAction(chaseAction); + */ } // Things to do when auto resets/inits. @@ -123,9 +137,66 @@ private void scheduleBootActions() { private void scheduleAutoActions() { // Power up to purple, and stay on. - PowerUpAction powerUpAction = new PowerUpAction(245, 0, 255, 90); - powerUpAction.setIntervalCount(ADDRESSABLE_LED_COUNT); - setAction(powerUpAction); + /* + * PowerUpAction powerUpAction = new PowerUpAction(245, 0, 255, 90); + * powerUpAction.setIntervalCount(ADDRESSABLE_LED_COUNT); + * setAction(powerUpAction); + */ + final File deployDir = Filesystem.getDeployDirectory(); + // ia.setOscillate(true); + // setAction(ia); + + final CommandGroup commandGroup = new CommandGroup(); + + String imagePath = deployDir.getAbsolutePath() + "/images/" + "blueredfade.png"; + ImageAction ia = new ImageAction(imagePath, 0.050).oscillate(); + commandGroup.addSequential(new ActionCommand(ia)); + commandGroup.addSequential(new WaitCommand(10)); + + imagePath = deployDir.getAbsolutePath() + "/images/" + "fade.png"; + ia = new ImageAction(imagePath, 0.050).oscillate(); + commandGroup.addSequential(new ActionCommand(ia)); + commandGroup.addSequential(new WaitCommand(10)); + + final String ia2Path = deployDir.getAbsolutePath() + "/images/" + "stripes.png"; + final ImageAction ia2 = new ImageAction(ia2Path, 0.050).oscillate().brightness(0.5); + commandGroup.addSequential(new ActionCommand(ia2)); + commandGroup.addSequential(new WaitCommand(10)); + + final String ia3Path = deployDir.getAbsolutePath() + "/images/" + "pulse.png"; + final ImageAction ia3 = new ImageAction(ia3Path, 0.050); + commandGroup.addSequential(new ActionCommand(ia3)); + commandGroup.addSequential(new WaitCommand(10)); + + imagePath = deployDir.getAbsolutePath() + "/images/" + "noisy-pulse.png"; + ia = new ImageAction(imagePath, 0.050).oscillate().brightness(0.8); + commandGroup.addSequential(new ActionCommand(ia)); + commandGroup.addSequential(new WaitCommand(10)); + + imagePath = deployDir.getAbsolutePath() + "/images/" + "noise.png"; + ia = new ImageAction(imagePath, 0.050).oscillate().brightness(0.1); + commandGroup.addSequential(new ActionCommand(ia)); + commandGroup.addSequential(new WaitCommand(10)); + + imagePath = deployDir.getAbsolutePath() + "/images/" + "burst.bmp"; + ia = new ImageAction(imagePath, 0.050); + commandGroup.addSequential(new ActionCommand(ia)); + commandGroup.addSequential(new WaitCommand(10)); + + imagePath = deployDir.getAbsolutePath() + "/images/" + "pulse-down.png"; + ia = new ImageAction(imagePath, 0.050).oscillate(); + commandGroup.addSequential(new ActionCommand(ia)); + commandGroup.addSequential(new WaitCommand(10)); + + final String burstPath = deployDir.getAbsolutePath() + "/images/" + "THfade.png"; + final ImageAction burstAction = new ImageAction(burstPath, 0.05).oscillate().brightness(200); + commandGroup.addSequential(new ActionCommand(burstAction)); + // commandGroup.addSequential(new WaitCommand(10)); + + // LedAction blackAction = new LedAction(0, 0, 0, 0); + // commandGroup.addSequential(new ActionCommand(blackAction)); + + Scheduler.getInstance().add(commandGroup); } // This is what we want to run when teleop starts. @@ -133,24 +204,25 @@ private void scheduleAutoActions() { private void scheduleTeleOpActions() { // Power up to purple, and stay on - should be on already in match. - PowerUpAction powerUpAction = new PowerUpAction(245, 0, 255, 90); + final PowerUpAction powerUpAction = new PowerUpAction(245, 0, 255, 90); powerUpAction.setIntervalCount(ADDRESSABLE_LED_COUNT); setAction(powerUpAction); // Using a command group with sequentials to force timely control of the leds. - CommandGroup commandGroup = new CommandGroup(); + final CommandGroup commandGroup = new CommandGroup(); // With 40s to remain, warning. commandGroup.addSequential(new WaitCommand(94)); - LedAction warnAction = new LedAction(255, 127, 0, 127); + final LedAction warnAction = new LedAction(255, 127, 0, 127); commandGroup.addSequential(new ActionCommand(warnAction)); // With 15s remain, go nuts to climb. - commandGroup.addSequential(new WaitCommand(24)); // 15 sec before match end (adding extra since it takes a bit to start an action) + commandGroup.addSequential(new WaitCommand(24)); // 15 sec before match end (adding extra since it takes a bit + // to start an action) - // Run the rainbow to indicate we need to climb. - ChaseAction chaseAction = new ChaseAction(255, 127, 0, 90); - chaseAction.setIntervalCount(-1); + // Run the chase to indicate we need to climb. + final ChaseAction chaseAction = new ChaseAction(255, 127, 0, 90); + chaseAction.setIntervalCount(-1); // run forever commandGroup.addSequential(new ActionCommand(chaseAction)); // Don't do anything for some time. @@ -213,19 +285,21 @@ public boolean isFlashlightOn() { } // Specifically sets the flashlight on/true or off/false. - public void setFlashlightState(boolean state) { + public void setFlashlightState(final boolean state) { flashlightOutput.set(state); } // Toggles the state of the flashlight. public void toggleFlashlight() { - boolean isOn = isFlashlightOn(); + final boolean isOn = isFlashlightOn(); setFlashlightState(!isOn); } @Override public void initDefaultCommand() { - // No default command - the output buffers are set in the reset* above. + String imagePath = Filesystem.getDeployDirectory().getAbsolutePath() + "/images/" + "fade.png"; + ImageAction ia = new ImageAction(imagePath).oscillate(); + setDefaultCommand(new ActionCommand(ia, 1000.0)); } @Override @@ -239,15 +313,16 @@ public void periodic() { // Set a color from the predefined wpilib Color // Brightness is on a scale of 0-255 - public void setColor(Color color, int brightness) { + public void setColor(final Color color, final int brightness) { setColor((int) color.red, (int) color.green, (int) color.blue, brightness); } // Set RGB color values. // RGB values are 0 (full off) - 255 (full on) // Brightness is on a scale of 0-255 - public void setColor(int red, int green, int blue, int brightness) { - double b = brightness / 255.0; + public void setColor(int red, int green, int blue, final int brightness) { + this.currentAction = null; // Clear any action that is running. + final double b = brightness / 255.0; red = (int) (red * b); green = (int) (green * b); @@ -255,7 +330,7 @@ public void setColor(int red, int green, int blue, int brightness) { // Create a buffer for all the LEDs, set all of them to the same value, and // output the buffer. - AddressableLEDBuffer buffer = new AddressableLEDBuffer(ADDRESSABLE_LED_COUNT); + final AddressableLEDBuffer buffer = new AddressableLEDBuffer(ADDRESSABLE_LED_COUNT); for (var i = 0; i < buffer.getLength(); i++) { buffer.setRGB(i, red, green, blue); } @@ -270,9 +345,6 @@ private class ActionRunner extends Thread { // allows the OS schedular a good slice to do things. private static final double MINIMUM_DELAY_SECONDS = 0.010; - // How long to delay/sleep when there's no action. - private static final double IDLE_DELAY_SECONDS = 0.250; - public void run() { // The thread should persist while the code does (forever). @@ -280,35 +352,29 @@ public void run() { // TODO: A watchdog should probably check to see if the thread died off // due to an exception and restart it. while (true) { - synchronized (actionLock) { if (currentAction != null) { - //System.out.println("ActionRunner: run"); - currentAction.run(); - - // If the current action is now done, remove it and loop back around. - if (currentAction.isFinished() == true) { - //System.out.println("ActionRunner: finished"); - currentAction = null; - continue; - } - // Delay the amount of time requested by the action. - double delay = currentAction.getDelay(); - if (delay < MINIMUM_DELAY_SECONDS) { - delay = MINIMUM_DELAY_SECONDS; + currentDelay = currentAction.getIntervalTime(); + if (currentDelay < MINIMUM_DELAY_SECONDS) { + currentDelay = MINIMUM_DELAY_SECONDS; } - //System.out.println("ActionRunner: delay"); - Timer.delay(delay); - continue; - } - } - - // Nothing to do; delay before looping. - Timer.delay(IDLE_DELAY_SECONDS); - } - } + if (timer.hasElapsed(currentDelay)) { + timer.reset(); + // System.out.println("ActionRunner: run"); + currentAction.run(); + + // If the current action is now done, remove it and loop back around. + if (currentAction.isFinished() == true) { + // System.out.println("ActionRunner: finished"); + currentAction = null; + } + } // currentDelay expired + } // currentAction != null + } // sync + } // while(true) + } // run() } } \ No newline at end of file diff --git a/src/main/java/frc/robot/status/Action.java b/src/main/java/frc/robot/status/actions/Action.java similarity index 67% rename from src/main/java/frc/robot/status/Action.java rename to src/main/java/frc/robot/status/actions/Action.java index 4b40927..2abd76a 100644 --- a/src/main/java/frc/robot/status/Action.java +++ b/src/main/java/frc/robot/status/actions/Action.java @@ -5,10 +5,21 @@ /* the project. */ /*----------------------------------------------------------------------------*/ -package frc.robot.status; +package frc.robot.status.actions; public class Action implements Runnable { + // How long to delay intervals. + protected double intervalTime = 0.0; + + public double getIntervalTime() { + return intervalTime; + } + + public void setIntervalTime(double intervalTime) { + this.intervalTime = intervalTime; + } + // If this returns true the action runner thread will stop invoking run on this action. public boolean isFinished() { return true; @@ -16,12 +27,11 @@ public boolean isFinished() { // How long to delay the action runner thread before calling run again. // The thread will have a minium that is enforced if this value is to low. - public double getDelay() { - return 0.0; - } + + // Reset the action. Used when adding to the action runner to reset anything that needs resetting. + public void reset() {} // Every loop of the action runner thread will call this method. - public void run() { - - } + public void run() {} + } diff --git a/src/main/java/frc/robot/status/ChaseAction.java b/src/main/java/frc/robot/status/actions/ChaseAction.java similarity index 98% rename from src/main/java/frc/robot/status/ChaseAction.java rename to src/main/java/frc/robot/status/actions/ChaseAction.java index 9830bad..8624be5 100644 --- a/src/main/java/frc/robot/status/ChaseAction.java +++ b/src/main/java/frc/robot/status/actions/ChaseAction.java @@ -5,7 +5,7 @@ /* the project. */ /*----------------------------------------------------------------------------*/ -package frc.robot.status; +package frc.robot.status.actions; public class ChaseAction extends LedAction { diff --git a/src/main/java/frc/robot/status/actions/ImageAction.java b/src/main/java/frc/robot/status/actions/ImageAction.java new file mode 100644 index 0000000..295b144 --- /dev/null +++ b/src/main/java/frc/robot/status/actions/ImageAction.java @@ -0,0 +1,158 @@ +package frc.robot.status.actions; + +import java.io.File; +import java.io.IOException; +import javax.imageio.ImageIO; +import edu.wpi.first.wpilibj.util.Color; +import java.awt.image.BufferedImage; + +/** + * Use an image file to set the addressable LEDs + * + * Provide the pathname to an image file. + * Interval can be set which is the delay between frames. + * Oscillate tells whether to start walking through the columns back at 0 or to count down when the end of the image is reached. + * Count is how many times to go through the image. LEDs will be left at the last "frame". -1 cycles forever. + * + * Each column in the image file will be treated as a "frame" or a full buffer. + * + * Height of the image does not matter, pixel selection will be scaled to the size of the buffer. + * This is a naive percentage scaling. If the LED being set is 1/2 way through the buffer, + * the pixel 1/2 way up the image will be used. + * e.g. If the buffer is 60 LEDs long and the image is 240 pixels high and LED 30 is being set, + * pixel 120 will be selected from the image. + * + * The "bottom" of the image is LED 0. 0,0 is usually the top, left of an image. + * For our purposes, LED 0 will get the highest numbered pixel. + * + */ +public class ImageAction extends LedAction { + + public static final double DEFAULT_INTERVAL = 0.050; + public static final int FOREVER = -1; // forever + + private File imageFile; + private BufferedImage image; + + private int currentColumn = 0; + private boolean oscillate = false; + private boolean goForward = true; + private double brightness = 1.0; + + public ImageAction() { + super(); + intervalTime = DEFAULT_INTERVAL; + intervalCount = FOREVER; + } + + public ImageAction(String pathname) { + this(pathname, DEFAULT_INTERVAL, FOREVER); + } + + public ImageAction(String pathname, double interval) { + this(pathname, interval, FOREVER); + } + + public ImageAction(String pathname, double interval, int count) { + super(); + intervalTime = interval; + try { + imageFile = new File(pathname); + image = ImageIO.read(imageFile); + intervalCount = count * image.getWidth(); + curIntCount = intervalCount; + } catch (IOException e) { + e.printStackTrace(); + System.out.println("Problem opening image. Check the path.\nImage path = " + pathname); + } + } + + public void reset() { + super.reset(); + this.currentColumn = 0; + } + + public ImageAction brightness(double brightness) { + setBrightness(brightness); + return this; + } + + public void setBrightness(double brightness) { + if (0.0 > brightness) { brightness = 0.0;} + if (1.0 < brightness) { brightness = 1.0;} + this.brightness = brightness; + } + + public ImageAction oscillate() { + this.oscillate = true; + return this; + } + + public void setOscillate(boolean b) { + oscillate = b; + } + + protected void updateBuffer() { + for (var i = 0; i < buffer.getLength(); i++) { + + // Scale the height of the image to the size of the buffer + // Do some shenanigans to force float arithmetic + double percent = (i * 1.0) / (buffer.getLength()-1); + int imageY = (int)((1.0 - percent) * (image.getHeight()-1)); + + int rgb = image.getRGB(currentColumn, imageY); + Color pixelColor = intToColor(rgb); + buffer.setLED(i, pixelColor); + } + + if (currentColumn < (image.getWidth()-1)) { + if (goForward) { + currentColumn++; + } else { + currentColumn--; + } + } else { // reached the end of the image + if (oscillate) { + goForward = false; + currentColumn--; + } else { + currentColumn=0; + } + } + + // Always move forward from the beginning + if (0 >= currentColumn) { + currentColumn = 0; // Handle edge case of drawing the zeroth column which then gets decremented. + goForward = true; + } + } + + /** + * Translate an integer representation INT_ARGB of a pixel's colors to + * a WPILib Color object. + * @param pixel + * @return WPILIB Color + */ + private Color intToColor(int pixel) { + int alpha = (pixel >> 24) & 0xff; + int redi = (pixel >> 16) & 0xff; + int greeni = (pixel >> 8) & 0xff; + int bluei = (pixel) & 0xff; + + double brightness = (alpha / 255.0) * this.brightness; + double red = brightness * (redi / 255.0); + double green = brightness * (greeni / 255.0); + double blue = brightness * (bluei / 255.0); + + return new Color(red, green, blue); + } + + public BufferedImage getImage() { + return image; + } + + public void setImage(BufferedImage image) { + this.image = image; + } + +} \ No newline at end of file diff --git a/src/main/java/frc/robot/status/LedAction.java b/src/main/java/frc/robot/status/actions/LedAction.java similarity index 82% rename from src/main/java/frc/robot/status/LedAction.java rename to src/main/java/frc/robot/status/actions/LedAction.java index 47a422a..5566991 100644 --- a/src/main/java/frc/robot/status/LedAction.java +++ b/src/main/java/frc/robot/status/actions/LedAction.java @@ -5,17 +5,16 @@ /* the project. */ /*----------------------------------------------------------------------------*/ -package frc.robot.status; +package frc.robot.status.actions; import edu.wpi.first.wpilibj.AddressableLEDBuffer; +import frc.robot.status.Status; public class LedAction extends Action { // How many times to run, less than 0 will run forever. protected int intervalCount = 1; - - // How long to delay intervals. - protected double intervalTime = 0.0; + protected int curIntCount = 1; // The current interval. // Buffer this action uses for sending to the LEDs. protected AddressableLEDBuffer buffer = new AddressableLEDBuffer(Status.ADDRESSABLE_LED_COUNT); @@ -41,12 +40,17 @@ public LedAction(int red, int green, int blue, int brightness) { } } - public void setIntervalTime(double intervalTime) { - this.intervalTime = intervalTime; - } - public void setIntervalCount(int intervalCount) { this.intervalCount = intervalCount; + this.curIntCount = intervalCount; + } + + public int getIntervalCount() { + return this.intervalCount; + } + + public int getCurrentIntervalCount() { + return this.curIntCount; } // Implementations should override the updateBuffer method. @@ -62,12 +66,19 @@ public boolean isFinished() { // If the intervalCount is greater than 0 or less than zero // we're not finished. The run() method will decrement if greater // and never finish if less than (a repeating pattern). - if (intervalCount == 0) { + if (curIntCount == 0) { return true; + } else { + return false; } - return false; } + @Override + public void reset() { + this.curIntCount = this.intervalCount; + } + + // Require by the parent Action class. // This is invoked by the running thread until isFinished returns true. @Override @@ -81,8 +92,8 @@ public void run() { // Only decrement the intervalCount if it's over 0. // Otherwise it may overflow backwords and cause problems. - if (intervalCount > 0) { - --intervalCount; + if (curIntCount > 0) { + --curIntCount; } } } diff --git a/src/main/java/frc/robot/status/PowerUpAction.java b/src/main/java/frc/robot/status/actions/PowerUpAction.java similarity index 97% rename from src/main/java/frc/robot/status/PowerUpAction.java rename to src/main/java/frc/robot/status/actions/PowerUpAction.java index 913c9f1..8b67d3a 100644 --- a/src/main/java/frc/robot/status/PowerUpAction.java +++ b/src/main/java/frc/robot/status/actions/PowerUpAction.java @@ -5,7 +5,7 @@ /* the project. */ /*----------------------------------------------------------------------------*/ -package frc.robot.status; +package frc.robot.status.actions; public class PowerUpAction extends LedAction { diff --git a/src/main/java/frc/robot/status/RainbowAction.java b/src/main/java/frc/robot/status/actions/RainbowAction.java similarity index 97% rename from src/main/java/frc/robot/status/RainbowAction.java rename to src/main/java/frc/robot/status/actions/RainbowAction.java index c5c37ec..9c3089e 100644 --- a/src/main/java/frc/robot/status/RainbowAction.java +++ b/src/main/java/frc/robot/status/actions/RainbowAction.java @@ -5,7 +5,7 @@ /* the project. */ /*----------------------------------------------------------------------------*/ -package frc.robot.status; +package frc.robot.status.actions; public class RainbowAction extends LedAction { diff --git a/src/main/java/frc/robot/status/ScannerAction.java b/src/main/java/frc/robot/status/actions/ScannerAction.java similarity index 98% rename from src/main/java/frc/robot/status/ScannerAction.java rename to src/main/java/frc/robot/status/actions/ScannerAction.java index 061d804..03f08d7 100644 --- a/src/main/java/frc/robot/status/ScannerAction.java +++ b/src/main/java/frc/robot/status/actions/ScannerAction.java @@ -5,7 +5,7 @@ /* the project. */ /*----------------------------------------------------------------------------*/ -package frc.robot.status; +package frc.robot.status.actions; public class ScannerAction extends LedAction { diff --git a/src/main/java/frc/robot/status/commands/ActionCommand.java b/src/main/java/frc/robot/status/commands/ActionCommand.java index 4f54fbf..094f614 100644 --- a/src/main/java/frc/robot/status/commands/ActionCommand.java +++ b/src/main/java/frc/robot/status/commands/ActionCommand.java @@ -1,10 +1,10 @@ package frc.robot.status.commands; -import com.team2363.logger.HelixEvents; +// import com.team2363.logger.HelixEvents; import edu.wpi.first.wpilibj.command.Command; -import frc.robot.status.Action; +import frc.robot.status.actions.Action; import frc.robot.status.Status; public class ActionCommand extends Command { @@ -12,21 +12,27 @@ public class ActionCommand extends Command { private Status status = null; private Action action = null; - // Default constructor - will toggle the light. + // Default constructor. public ActionCommand(Action action) { - status = Status.getStatus(); - requires(status); + this(action, 0.0); // Make the command complete instantly. + } + public ActionCommand(Action action, double timeout) { + super(timeout); + this.status = Status.getStatus(); + requires(status); this.action = action; } + // Called just before this Command runs the first time @Override protected void initialize() { - HelixEvents.getInstance().addEvent("STATUS", "Starting ActionCommand"); + // HelixEvents.getInstance().addEvent("STATUS", "Starting ActionCommand"); // This will set our action to run on the subsystem. // This action will run in the dedicated thread to output the rainbow pattern. + action.reset(); status.setAction(action); } @@ -41,13 +47,13 @@ protected void execute() { protected boolean isFinished() { // This command literally just sets the action on the subsystem. // So there's nothing to do. - return true; + return this.isTimedOut(); } // Called once after isFinished returns true @Override protected void end() { - HelixEvents.getInstance().addEvent("STATUS", "Ending ActionCommand"); + // HelixEvents.getInstance().addEvent("STATUS", "Ending ActionCommand"); } // Called when another command which requires one or more of the same diff --git a/src/main/java/frc/robot/status/commands/ToggleFlashlight.java b/src/main/java/frc/robot/status/commands/ToggleFlashlight.java index bcd3a88..1a13e4b 100644 --- a/src/main/java/frc/robot/status/commands/ToggleFlashlight.java +++ b/src/main/java/frc/robot/status/commands/ToggleFlashlight.java @@ -1,7 +1,7 @@ package frc.robot.status.commands; -import com.team2363.logger.HelixEvents; +// import com.team2363.logger.HelixEvents; import edu.wpi.first.wpilibj.command.Command; import frc.robot.status.Status; @@ -33,7 +33,7 @@ public ToggleFlashlight(boolean state) { // Called just before this Command runs the first time @Override protected void initialize() { - HelixEvents.getInstance().addEvent("STATUS", "Starting ToggleFlashlight"); + // HelixEvents.getInstance().addEvent("STATUS", "Starting ToggleFlashlight"); // The command can either toggle as is, or set to a specific sate. if (forceSet == true) { @@ -59,7 +59,7 @@ protected boolean isFinished() { // Called once after isFinished returns true @Override protected void end() { - HelixEvents.getInstance().addEvent("STATUS", "Ending ToggleFlashlight"); + // HelixEvents.getInstance().addEvent("STATUS", "Ending ToggleFlashlight"); } // Called when another command which requires one or more of the same