diff --git a/simgui-ds.json b/simgui-ds.json new file mode 100644 index 0000000..73cc713 --- /dev/null +++ b/simgui-ds.json @@ -0,0 +1,92 @@ +{ + "keyboardJoysticks": [ + { + "axisConfig": [ + { + "decKey": 65, + "incKey": 68 + }, + { + "decKey": 87, + "incKey": 83 + }, + { + "decKey": 69, + "decayRate": 0.0, + "incKey": 82, + "keyRate": 0.009999999776482582 + } + ], + "axisCount": 3, + "buttonCount": 4, + "buttonKeys": [ + 90, + 88, + 67, + 86 + ], + "povConfig": [ + { + "key0": 328, + "key135": 323, + "key180": 322, + "key225": 321, + "key270": 324, + "key315": 327, + "key45": 329, + "key90": 326 + } + ], + "povCount": 1 + }, + { + "axisConfig": [ + { + "decKey": 74, + "incKey": 76 + }, + { + "decKey": 73, + "incKey": 75 + } + ], + "axisCount": 2, + "buttonCount": 4, + "buttonKeys": [ + 77, + 44, + 46, + 47 + ], + "povCount": 0 + }, + { + "axisConfig": [ + { + "decKey": 263, + "incKey": 262 + }, + { + "decKey": 265, + "incKey": 264 + } + ], + "axisCount": 2, + "buttonCount": 6, + "buttonKeys": [ + 260, + 268, + 266, + 261, + 269, + 267 + ], + "povCount": 0 + }, + { + "axisCount": 0, + "buttonCount": 0, + "povCount": 0 + } + ] +} diff --git a/src/main/java/frc/kelrotlib/utils/TunableNumber.java b/src/main/java/frc/kelrotlib/utils/TunableNumber.java new file mode 100644 index 0000000..543abce --- /dev/null +++ b/src/main/java/frc/kelrotlib/utils/TunableNumber.java @@ -0,0 +1,93 @@ +package frc.kelrotlib.utils; + +import edu.wpi.first.networktables.*; +import frc.robot.Constants; +import dev.doglog.DogLog; + +import java.util.EnumSet; +import java.util.function.Consumer; + +public class TunableNumber { + private final NetworkTableEntry entry; + private double lastValue; + private NetworkTableInstance inst = NetworkTableInstance.getDefault(); + + + /** + * Constructor with onChange callback + * @param key The name of the tunable value + * @param defaultValue The default value if not set on the dashboard + * @param onChange A callback that runs whenever the value changes + */ + public TunableNumber(String key, double defaultValue, Consumer onChange) { + this.lastValue = defaultValue; + + // Get or create the NetworkTable entry for this tunable number + entry = NetworkTableInstance.getDefault() + .getTable("SmartDashboard") + .getEntry("/Tuning" + "/" + key); + + // Set the initial value on the dashboard + entry.setDouble(defaultValue); + + // Add a listener to detect changes in the entry + inst.addListener( + entry, + EnumSet.of(NetworkTableEvent.Kind.kValueAll), + event -> { + double newValue = entry.getDouble(lastValue); + + // If the value changed and tuningMode is ON, accept the change + if(this.lastValue != newValue && Constants.tuningMode) { + DogLog.log("/Tuning" + "/" + key, entry.getDouble(lastValue)); + this.lastValue = newValue; + onChange.accept(lastValue); // call the callback + } else { + // Otherwise, reset the value to the last known value + entry.setDouble(this.lastValue); + } + }); + } + + /** + * Constructor without onChange callback + * @param key The name of the tunable value + * @param defaultValue The default value if not set on the dashboard + */ + public TunableNumber(String key, double defaultValue) { + this.lastValue = defaultValue; + + // Get or create the NetworkTable entry for this tunable number + entry = NetworkTableInstance.getDefault() + .getTable("SmartDashboard") + .getEntry("/Tuning" + "/" + key); + + // Set the initial value on the dashboard + entry.setDouble(defaultValue); + + // Add a listener to detect changes in the entry + inst.addListener( + entry, + EnumSet.of(NetworkTableEvent.Kind.kValueAll), + event -> { + double newValue = entry.getDouble(lastValue); + + // If the value changed and tuningMode is ON, accept the change + if(this.lastValue != newValue && Constants.tuningMode) { + DogLog.log("/Tuning" + "/" + key, entry.getDouble(lastValue)); + this.lastValue = newValue; + } else { + // Otherwise, reset the value to the last known value + entry.setDouble(this.lastValue); + } + }); + } + + /* + * Return the current value of this tunable number + * This always returns the last accepted value + */ + public double get() { + return lastValue; + } +} diff --git a/src/main/java/frc/robot/Constants.java b/src/main/java/frc/robot/Constants.java index 56eb8c9..eeb5acc 100644 --- a/src/main/java/frc/robot/Constants.java +++ b/src/main/java/frc/robot/Constants.java @@ -5,5 +5,7 @@ package frc.robot; public final class Constants { - + + public static boolean tuningMode = true; + } \ No newline at end of file diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index f22fc1b..6a4930e 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -4,9 +4,13 @@ package frc.robot; +import edu.wpi.first.wpilibj.util.Color; import edu.wpi.first.wpilibj2.command.Command; +import frc.kelrotlib.utils.TunableNumber; +import frc.robot.subsystems.ExampleSubsystem; +import frc.robot.subsystems.TunableNumberExample; public class RobotContainer { - + private final TunableNumberExample yTunableNumberExample = new TunableNumberExample(); public RobotContainer() { configureBindings(); } diff --git a/src/main/java/frc/robot/subsystems/ExampleSubsystem.java b/src/main/java/frc/robot/subsystems/ExampleSubsystem.java index 0c013ba..8331a42 100644 --- a/src/main/java/frc/robot/subsystems/ExampleSubsystem.java +++ b/src/main/java/frc/robot/subsystems/ExampleSubsystem.java @@ -3,7 +3,9 @@ import edu.wpi.first.wpilibj2.command.SubsystemBase; public class ExampleSubsystem extends SubsystemBase { - /** Creates a new ExampleSubsystem. */ + + + /* Creates a new ExampleSubsystem. */ public ExampleSubsystem() { } diff --git a/src/main/java/frc/robot/subsystems/TunableNumberExample.java b/src/main/java/frc/robot/subsystems/TunableNumberExample.java new file mode 100644 index 0000000..961a311 --- /dev/null +++ b/src/main/java/frc/robot/subsystems/TunableNumberExample.java @@ -0,0 +1,30 @@ +package frc.robot.subsystems; + +import edu.wpi.first.wpilibj2.command.SubsystemBase; +import frc.kelrotlib.utils.TunableNumber; + +public class TunableNumberExample extends SubsystemBase { + + private final TunableNumber newnumber = new TunableNumber("sa", 0); + + private final TunableNumber newnumber2 = new TunableNumber("test2", 0, value -> { + System.out.println("Tunable Number is changed, new number is" + value); + + // Usage is not like motor.setVoltage(newnumber) + // You should motor.setVoltage(newnumber.get()) + }); + /** Creates a new ExampleSubsystem. */ + public TunableNumberExample() { + + } + + @Override + public void periodic() { + // This method will be called once per scheduler run + } + + @Override + public void simulationPeriodic() { + // This method will be called once per scheduler run during simulation + } +} diff --git a/vendordeps/DogLog.json b/vendordeps/DogLog.json new file mode 100644 index 0000000..2ee13f6 --- /dev/null +++ b/vendordeps/DogLog.json @@ -0,0 +1,20 @@ +{ + "javaDependencies": [ + { + "groupId": "com.github.jonahsnider", + "artifactId": "doglog", + "version": "2025.8.1" + } + ], + "fileName": "DogLog.json", + "frcYear": "2025", + "jsonUrl": "https://doglog.dev/vendordep.json", + "name": "DogLog", + "jniDependencies": [], + "mavenUrls": [ + "https://jitpack.io" + ], + "cppDependencies": [], + "version": "2025.8.1", + "uuid": "65592ce1-2251-4a31-8e4b-2df20dacebe4" +} \ No newline at end of file