Skip to content
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
62 changes: 33 additions & 29 deletions src/main/java/frc/kelrotlib/leds/Led.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import static edu.wpi.first.units.Units.MetersPerSecond;
import static edu.wpi.first.units.Units.Seconds;

import java.util.HashMap;

import edu.wpi.first.wpilibj.AddressableLED;
import edu.wpi.first.wpilibj.AddressableLEDBuffer;
import edu.wpi.first.wpilibj.AddressableLEDBufferView;
Expand All @@ -17,78 +15,84 @@
public class Led extends SubsystemBase{ //a Java inheritance example
private AddressableLED m_led;
private AddressableLEDBuffer m_buffer;
private HashMap<Integer, AddressableLEDBufferView> m_groupList;
private HashMap<Integer, LEDPattern> m_patternList;
private LEDPattern k_defaultPattern = LEDPattern.solid(Color.kBlack);
private AddressableLEDBufferView[] m_groupList;
private LEDPattern[] m_patternList;

private LEDPattern k_defaultPattern;

public Led() {
public Led(int[][] ledGroups) {
m_led = new AddressableLED(LedConstants.kLedPort); //every variable you might change later (ports, length etc.) should be added to Constants.java*
m_buffer = new AddressableLEDBuffer(LedConstants.kLedLength); // * this way every port and important variable is in one place.
m_led.setLength(LedConstants.kLedLength); //setting the length takes a lot of load so do it only one time when possible
m_led.start();

m_groupList = new HashMap<Integer, AddressableLEDBufferView>(); //I decided to use Integers for the keys as it is much more straight-forward, in future uses the keys can be String's for more complicated group identification needs.
m_patternList = new HashMap<Integer, LEDPattern>(); //For this version of grouping we need to store previous patterns for each group
k_defaultPattern = LEDPattern.solid(Color.kBlack);

m_groupList = new AddressableLEDBufferView[ledGroups.length]; //create a new groupList with the same length as the ledGroups array
m_patternList = new LEDPattern[ledGroups.length]; //create a new patternList with the same length as the ledGroups array
for (int i = 0; i < ledGroups.length; i++) {
createGroup(ledGroups[i][0], ledGroups[i][1], i);
}

setDefaultCommand(runPattern(k_defaultPattern).withName("Off")); //set all leds to off/black on start
}

public void createGroup(int startingIndex, int endingIndex, Integer groupID) { //infinite amount of groups creatable, without complicating the code
public void createGroup(int startingIndex, int endingIndex, int groupID) {
AddressableLEDBufferView group = m_buffer.createView(startingIndex, endingIndex); //create new group(view)
m_groupList.put(groupID, group);
m_patternList.put(groupID, k_defaultPattern); //initially set the defaultPattern, so the runPattern command doesn't break
m_groupList[groupID] = group; //add the group to the groupList
m_patternList[groupID] = k_defaultPattern; //add the default pattern to the patternList
}

public void setSolidColor(Color color, Integer[] groupIDs){
public void setSolidColor(Color color, int[] groupIDs){
LEDPattern solidColorPattern = LEDPattern.solid(color);
for (int i = 0; i < groupIDs.length; i++) { //update the latest pattern for every LED group given
m_patternList.replace(groupIDs[i], solidColorPattern); //I love hashmap it is just so cool
m_patternList[groupIDs[i]] = solidColorPattern; //replace the pattern for the groupID with the new solid color pattern
}
runPattern();
runPattern().schedule();
}

public void setBlinkColor(Color color, double interval, Integer[] groupIDs){
public void setBlinkColor(Color color, double interval, int[] groupIDs){
LEDPattern base = LEDPattern.solid(color);
LEDPattern blinkPattern = base.blink(Seconds.of(interval)); //synchronised blink, wpilib also has support for asynchronised blink
for (int i = 0; i < groupIDs.length; i++) {
m_patternList.replace(groupIDs[i], blinkPattern);
m_patternList[groupIDs[i]] = blinkPattern;
}
runPattern();
runPattern().schedule();
}

public void rainbow(Integer[] groupIDs){
public void rainbow(int[] groupIDs){
LEDPattern rainbow = LEDPattern.rainbow(255, 128); //all hues at maximum saturation and *half* brightness
LEDPattern scrollingRainbow = rainbow.scrollAtAbsoluteSpeed(MetersPerSecond.of(1), LedConstants.kLedSpacing); //moves/scrolls the effect at a speed of 1 meter per second
for (int i = 0; i < groupIDs.length; i++) {
m_patternList.replace(groupIDs[i], scrollingRainbow);
m_patternList[groupIDs[i]] = scrollingRainbow;
}
runPattern();
runPattern().schedule();
}

public void turnOff(){
runPattern(k_defaultPattern);
setSolidColor(Color.kBlack, new int[] {0, 1, 2}); //turn off all LEDs by setting them to black
}

private Command runPattern(){ //A command is used as it doesn't allow actions to run simultaneously, for this usage it is crucial, because we need to stop the previous patterns and start the new ones.
public Command runPattern(){ //A command is used as it doesn't allow actions to run simultaneously, for this usage it is crucial, because we need to stop the previous patterns and start the new ones.
return run(() -> {
for (Integer i : m_groupList.keySet()) { //parsing through every key in the groupList HashMap
m_patternList.get(i).applyTo(m_groupList.get(i)); //getting every setted pattern and applying it to the ID'd LED Group
for (int i = 0; i < m_groupList.length; i++) {
m_patternList[i].applyTo(m_groupList[i]); //apply the pattern to the group
}
});
}).ignoringDisable(true);
}

private Command runPattern(LEDPattern pattern) { //might get removed later.
private Command runPattern(LEDPattern pattern) {
return run(() -> {
pattern.applyTo(m_buffer);
});
}).ignoringDisable(true);
}

@Override
public void periodic() { //update the data every 20ms
public void periodic() {
m_led.setData(m_buffer);
}

@Override
public void simulationPeriodic() {
}
}
}
8 changes: 7 additions & 1 deletion src/main/java/frc/robot/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ public final class Constants {
public static class LedConstants {
public static final int kLedPort = 6; //PWM port on RoborIO
public static final int kLedLength = 60; //led count
public static final Distance kLedSpacing = Meters.of(1/ 60.0); // density of 120 LEDs per meter
public static final Distance kLedSpacing = Meters.of(1/ 60.0); // density of 60 LEDs per meter
public static final int[][] kledGroups = {
new int[] {0,19}, //group 0
new int[] {20,39}, // group 1
new int[] {40,59} // group 2
};

}

}
13 changes: 7 additions & 6 deletions src/main/java/frc/robot/RobotContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,25 @@

package frc.robot;

import frc.robot.Constants.LedConstants;
import frc.robot.subsystems.LedSubsystem;
import edu.wpi.first.wpilibj.util.Color;
import edu.wpi.first.wpilibj2.command.Command;
public class RobotContainer {
private final LedSubsystem m_led = new LedSubsystem();
private final LedSubsystem m_led = new LedSubsystem(LedConstants.kledGroups);

public RobotContainer() {
m_led.createGroup(0, 29, 1); //indexing: in a 60 led strip, first LED is index 0 and the last led is index 59
m_led.createGroup(30, 59, 2);

m_led.setSolidColor(Color.kFirstBlue, new Integer[] {1,2}); //The library Color includes many color presets, but it is also possible to use RGB values to create "Color"s

m_led.setBlinkColor(Color.kRed, 3, new int[]{0,1,2});
configureBindings();
}

private void configureBindings() {
}

public LedSubsystem getLedSubsystem() {
return m_led;
}

public Command getAutonomousCommand() {
return null;
}
Expand Down
5 changes: 2 additions & 3 deletions src/main/java/frc/robot/subsystems/LedSubsystem.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ public class LedSubsystem extends Led {
// Inherits all methods and properties from the KelrotLib Led class
// You can add additional methods or override existing ones if needed

public LedSubsystem() {
super(); // Call the constructor of the parent class
// Additional initialization if necessary
public LedSubsystem(int[][] ledGroups) {
super(ledGroups);
}
}
35 changes: 35 additions & 0 deletions vendordeps/AdvantageKit.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"fileName": "AdvantageKit.json",
"name": "AdvantageKit",
"version": "4.1.2",
"uuid": "d820cc26-74e3-11ec-90d6-0242ac120003",
"frcYear": "2025",
"mavenUrls": [
"https://frcmaven.wpi.edu/artifactory/littletonrobotics-mvn-release/"
],
"jsonUrl": "https://github.com/Mechanical-Advantage/AdvantageKit/releases/latest/download/AdvantageKit.json",
"javaDependencies": [
{
"groupId": "org.littletonrobotics.akit",
"artifactId": "akit-java",
"version": "4.1.2"
}
],
"jniDependencies": [
{
"groupId": "org.littletonrobotics.akit",
"artifactId": "akit-wpilibio",
"version": "4.1.2",
"skipInvalidPlatforms": false,
"isJar": false,
"validPlatforms": [
"linuxathena",
"linuxx86-64",
"linuxarm64",
"osxuniversal",
"windowsx86-64"
]
}
],
"cppDependencies": []
}
38 changes: 38 additions & 0 deletions vendordeps/PathplannerLib.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"fileName": "PathplannerLib.json",
"name": "PathplannerLib",
"version": "2025.2.6",
"uuid": "1b42324f-17c6-4875-8e77-1c312bc8c786",
"frcYear": "2025",
"mavenUrls": [
"https://3015rangerrobotics.github.io/pathplannerlib/repo"
],
"jsonUrl": "https://3015rangerrobotics.github.io/pathplannerlib/PathplannerLib.json",
"javaDependencies": [
{
"groupId": "com.pathplanner.lib",
"artifactId": "PathplannerLib-java",
"version": "2025.2.6"
}
],
"jniDependencies": [],
"cppDependencies": [
{
"groupId": "com.pathplanner.lib",
"artifactId": "PathplannerLib-cpp",
"version": "2025.2.6",
"libName": "PathplannerLib",
"headerClassifier": "headers",
"sharedLibrary": false,
"skipInvalidPlatforms": true,
"binaryPlatforms": [
"windowsx86-64",
"linuxx86-64",
"osxuniversal",
"linuxathena",
"linuxarm32",
"linuxarm64"
]
}
]
}
Loading