Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Led opacity #117

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 62 additions & 23 deletions src/main/java/frc/robot/subsystems/leds/LEDLayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,74 +3,113 @@
import edu.wpi.first.wpilibj.util.Color;

public class LEDLayer {
private final Color[] ledArray;
private final Color[] colorArray;
private final double[] opacityArray;

public LEDLayer(int length) {
ledArray = new Color[length];
colorArray = new Color[length];
opacityArray = new double[length];
}

/**
* Sets an LED at a specified index.
* @param i The LED index to set.
* @param color The color to set the LED at index i to (null is equivalent to transparent).
* @param opacity The opacity to set the LED at index i to
*/
public void setLED(int i, Color color) {
ledArray[i] = color;
public void setLED(int i, Color color, double opacity) {
colorArray[i] = color;
opacityArray[i] = opacity;
}

public void setLED(int i, Color color){
setLED(i, color, 1);
}

/**
* Gets the color of an LED at a specified index.
* Gets the color of the LED at a specified index.
* @param i The LED index to retrieve.
* @return The color of the LED at index i.
*/
public Color getLED(int i) {
return ledArray[i];
public Color getLEDColor(int i) {
return colorArray[i];
}

/**
* Gets the opacity of the LED at a specified index
* @param i The LED index to retrieve.
* @return The opacity of the LED at index i.
*/
public double getLEDOpacity(int i){
return opacityArray[i];
}

/**
* Moves the leds up by an increment
* @param inc the number of leds to move up by
* @param color the color to set at the bottom
* @param inc The number of leds to move up by
* @param color The color to set at the bottom
* @param opacity The opacity to set the new leds at
*/
public void incrementColors(int inc, Color color) {
for (int i = 0; i < ledArray.length - inc; i++) {
setLED(i, getLED(i + inc));
public void incrementColors(int inc, Color color, double opacity) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so i realized that this actually pushes the colors towards 0 which isn't explained in either the method name or the comments

for (int i = 0; i < colorArray.length - inc; i++) {
setLED(i, getLEDColor(i + inc), getLEDOpacity(i +inc));
}
for (int i = ledArray.length - inc; i < ledArray.length; i++) {
setLED(i, color);
for (int i = colorArray.length - inc; i < colorArray.length; i++) {
setLED(i, color, opacity);
}
}

public void incrementColors(int inc, Color color){
incrementColors(inc, color, 1);
}

/**
* Fills the layer with a solid color.
* @param color The color to fill the layer with.
* @param opacity The opacity to fill the layer with
*/
public void fillColor(Color color) {
for (int i = 0; i < ledArray.length; i++) {
setLED(i, color);
public void fillColor(Color color, double opacity) {
for (int i = 0; i < colorArray.length; i++) {
setLED(i, color, opacity);
}
}

public void fillColor(Color color){
fillColor(color, 1);
}

/**
* Fills the layer with alternating groups of "on" and "off" LEDs. "off" leds are set to null (transparent).
* @param onGroupLength The length of the "on" group.
* @param offGroupLength The length of the "off" group.
* @param borderLength The length of a gradient border which fades in at the edge of each "on" length
* @param color The color to set the "on" LEDs.
* @param opacity The opacity of the "on" LEDs.
* @param offset The number of LEDs to offset the base by
*/
public void fillGrouped(int onGroupLength, int offGroupLength, Color color) {
for (int i = 0; i < ledArray.length; i++) {
if (i % (onGroupLength + offGroupLength) < onGroupLength) {
setLED(i, color);
public void fillGrouped(int onGroupLength, int offGroupLength, int borderLength, Color color, double opacity, int offset) {
for (int i = 0; i < colorArray.length; i++) {
int ledNumInSegment = (i + offset) % (2 * borderLength + onGroupLength + offGroupLength);
if (ledNumInSegment < borderLength){
setLED(i, color, opacity * (ledNumInSegment + 1) / (borderLength + 1));
} else if (ledNumInSegment < onGroupLength + borderLength) {
setLED(i, color, opacity);
} else if(ledNumInSegment < onGroupLength + borderLength * 2){
setLED(i, color, opacity * (1 - ((ledNumInSegment - onGroupLength - borderLength + 1.) / (borderLength + 1))));
} else {
setLED(i, null);
setLED(i, null, opacity);
}
}
}

public void fillGrouped(int onGroupLength, int offGroupLength, Color color){
fillGrouped(onGroupLength, offGroupLength, 0, color, 1, 0);
}

/**
* Resets the layer by setting all LEDs to null (transparent).
*/
public void reset() {
fillColor(null);
fillColor(null, 1);
}
}
20 changes: 18 additions & 2 deletions src/main/java/frc/robot/subsystems/leds/LEDStrip.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import edu.wpi.first.wpilibj.AddressableLED;
import edu.wpi.first.wpilibj.AddressableLEDBuffer;
import edu.wpi.first.wpilibj.util.Color;

public class LEDStrip {
private final AddressableLED led;
Expand Down Expand Up @@ -30,9 +31,24 @@ public void setBuffer() {
*/
public void addLayer(LEDLayer layer) {
for (int i = 0; i < ledLength; i++) {
if (layer.getLED(i) != null) {
ledBuffer.setLED(i, layer.getLED(i));
if (layer.getLEDColor(i) != null) {
ledBuffer.setLED(i, calcColorWithOpacity(ledBuffer.getLED(i), layer.getLEDColor(i), layer.getLEDOpacity(i)));
}
}
}

/**
* Calculates the desired color when led layering
* @param baseColor The color of the lower layer led
* @param topColor The color of the led being added
* @param opacity The opacity of the top led
* @return The color of the led layers combined
*/
public Color calcColorWithOpacity(Color baseColor, Color topColor, double opacity){
double r = (((1 - opacity) * baseColor.red) + (opacity * topColor.red));
double g = (((1 - opacity) * baseColor.green) + (opacity * topColor.green));
double b = (((1 - opacity) * baseColor.blue) + (opacity * topColor.blue));

return(new Color(r, g, b));
}
}
24 changes: 11 additions & 13 deletions src/main/java/frc/robot/subsystems/leds/LEDSubsystem.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ public class LEDSubsystem extends SubsystemBase {

private final Timer fadeTimer = new Timer();
private static final double COLOR_SENSOR_FADE_PERIOD_SECONDS = .5;
private final double COLOR_PULSE_SPEED = .2;
private boolean colorSensorOff = false;
private double colorOffset = 0;

private static final double BRIGHTNESS_SCALE_FACTOR = 0.25;
private static final double INPUT_DEADZONE = 0.35;
Expand Down Expand Up @@ -92,10 +94,14 @@ public void periodic() {

// Update colorSensorLayer - pulsing red grouped indicators to indicate a color sensor failure.
if (colorSensorOff) {
colorOffset += inc * COLOR_PULSE_SPEED;
colorOffset %= LED_LENGTH;
fadeTimer.start();
colorSensorLayer.fillGrouped(
5, 10,
crossFadeWithTime(COLOR_SENSOR_OFF_COLOR, baseColor, fadeTimer.get(), COLOR_SENSOR_FADE_PERIOD_SECONDS)
5, 10, 5,
COLOR_SENSOR_OFF_COLOR,
crossFadeWithTime(fadeTimer.get(), COLOR_SENSOR_FADE_PERIOD_SECONDS),
(int) colorOffset
);
} else {
fadeTimer.stop();
Expand Down Expand Up @@ -135,22 +141,14 @@ public void displayTagDetected() {

/**
* Cross-fades between two colors using a sinusoidal scaling function.
* @param color The color to set.
* @param fadeColor The color to fade into.
* @param currentTimeSeconds The current elapsed time of fading.
* @param periodSeconds The period of the fade function, in seconds.
* @return The scaled and faded color.
* @return The scale to set the opacity to
*/
private static Color crossFadeWithTime(Color color, Color fadeColor, double currentTimeSeconds, double periodSeconds) {
private static double crossFadeWithTime(double currentTimeSeconds, double periodSeconds) {
// The [0.0, 1.0] brightness scale to scale the color by. Scale = 1/2 * cos(t) + 1/2 where
// t is scaled to produce the desired period.
double scale = 0.5 * Math.cos(currentTimeSeconds * 2 * Math.PI / periodSeconds) + 0.5;

return new Color(
color.red * scale + fadeColor.red * (1 - scale),
color.green * scale + fadeColor.green * (1 - scale),
color.blue * scale + fadeColor.blue * (1 - scale)
);
return(0.5 * Math.cos(currentTimeSeconds * 2 * Math.PI / periodSeconds) + 0.5);
}

/**
Expand Down