Skip to content
Open
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Binary file added src/main/deploy/images/THfade.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/main/deploy/images/burst.bmp
Binary file not shown.
Binary file added src/main/deploy/images/fade.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/main/deploy/images/noise.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/main/deploy/images/noisy-pulse.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/main/deploy/images/pulse-down.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/main/deploy/images/pulse.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/main/deploy/images/stripe.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/main/deploy/images/stripes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
48 changes: 48 additions & 0 deletions src/main/java/frc/robot/command_groups/LEDDemoCG.java
Original file line number Diff line number Diff line change
@@ -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)));
}

}
172 changes: 119 additions & 53 deletions src/main/java/frc/robot/status/Status.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

//
Expand Down Expand Up @@ -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).
Expand Down Expand Up @@ -91,66 +101,128 @@ 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
}
}

// Things to do when boot starts.
// 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.
// This can be scheduled commands, command groups, etc.
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.
// This can be scheduled commands, command groups, etc.
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.
Expand Down Expand Up @@ -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
Expand All @@ -239,23 +313,24 @@ 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);
blue = (int) (blue * b);

// 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);
}
Expand All @@ -270,45 +345,36 @@ 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).
//
// 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()
}
}
Loading