From 3b623eafd63b9300ef03d8f1921a76c9dff25d7f Mon Sep 17 00:00:00 2001 From: Arav Chadha Date: Mon, 4 Dec 2023 15:47:53 -0800 Subject: [PATCH 1/4] Initial Entry Position Stuff --- .vscode/launch.json | 12 ++++-- simgui.json | 14 ++++++- src/main/java/frc/team3128/Constants.java | 5 +++ .../common/utility/NAR_Shuffleboard.java | 38 ++++++++++++------- .../team3128/subsystems/NAR_PIDSubsystem.java | 20 ++++++++-- 5 files changed, 68 insertions(+), 21 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index c9c9713..703b4ff 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,18 +4,24 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ - + { + "type": "java", + "name": "Main", + "request": "launch", + "mainClass": "frc.team3128.Main", + "projectName": "3128-robot-2023-prebot" + }, { "type": "wpilib", "name": "WPILib Desktop Debug", "request": "launch", - "desktop": true, + "desktop": true }, { "type": "wpilib", "name": "WPILib roboRIO Debug", "request": "launch", - "desktop": false, + "desktop": false } ] } diff --git a/simgui.json b/simgui.json index ec8e49b..023c628 100644 --- a/simgui.json +++ b/simgui.json @@ -4,6 +4,9 @@ "/FMSInfo": "FMSInfo", "/Shuffleboard/Drivetrain/Drivetrain": "Subsystem", "/Shuffleboard/Drivetrain/Gyro": "Gyro", + "/Shuffleboard/Elevator/Elevator": "Subsystem", + "/Shuffleboard/Elevator/PID_Controller": "Subsystem", + "/Shuffleboard/Elevator/TEST2": "Subsystem", "/Shuffleboard/Field/field": "Field2d", "/Shuffleboard/General/Gyro": "Gyro", "/Shuffleboard/Vision/RCONTROLLER": "PIDController", @@ -12,17 +15,26 @@ "/Shuffleboard/VisionPID/RCONTROLLER": "PIDController", "/Shuffleboard/VisionPID/XCONTROLLER": "PIDController", "/Shuffleboard/VisionPID/YCONTROLLER": "PIDController", + "/Shuffleboard/Wrist/PID_Controller": "Subsystem", + "/Shuffleboard/Wrist/TEST2": "Subsystem", + "/Shuffleboard/Wrist/Wrist": "Subsystem", "/Shuffleboard/intake/PID Controller": "PIDController", "/Shuffleboard/pivot/Pivot-PID": "PIDController", "/Shuffleboard/telescope/tele-PID": "PIDController", "/SmartDashboard/CommandScheduler": "Scheduler", - "/SmartDashboard/Field": "Field2d" + "/SmartDashboard/Field": "Field2d", + "/SmartDashboard/TESTTTT": "PIDController" }, "windows": { "/Shuffleboard/Field/field": { "window": { "visible": true } + }, + "/SmartDashboard/Field": { + "window": { + "visible": true + } } } } diff --git a/src/main/java/frc/team3128/Constants.java b/src/main/java/frc/team3128/Constants.java index 0774c4d..a24dcbe 100644 --- a/src/main/java/frc/team3128/Constants.java +++ b/src/main/java/frc/team3128/Constants.java @@ -25,6 +25,11 @@ public class Constants { + public static class ShuffleboardConstants { + public static final int WINDOW_HEIGHT = 10; + public static final int WINDOW_WIDTH = 10; + } + public static class TrajectoryConstants { public static final Rotation2d HEADING = Rotation2d.fromDegrees(180); diff --git a/src/main/java/frc/team3128/common/utility/NAR_Shuffleboard.java b/src/main/java/frc/team3128/common/utility/NAR_Shuffleboard.java index f6f9b1e..8006803 100644 --- a/src/main/java/frc/team3128/common/utility/NAR_Shuffleboard.java +++ b/src/main/java/frc/team3128/common/utility/NAR_Shuffleboard.java @@ -12,6 +12,7 @@ import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; import edu.wpi.first.wpilibj.shuffleboard.ShuffleboardTab; import edu.wpi.first.wpilibj.shuffleboard.SimpleWidget; +import static frc.team3128.Constants.ShuffleboardConstants.*; /** * Wrapper for {@link Shuffleboard} @@ -49,27 +50,29 @@ public void update() { } } - private static HashMap> tabs = new HashMap>();; + private static HashMap> tabs = new HashMap>(); + public static boolean[][] entryPositions = new boolean[WINDOW_HEIGHT][WINDOW_WIDTH]; // Make private later + /** - * Creates a new tab entry - * - * @param tabName the title of the new tab - */ + * Creates a new tab entry + * + * @param tabName the title of the new tab + */ private static void create_tab(String tabName) { tabs.put(tabName, new HashMap()); } /** - * Displays a value in Shuffleboard - * - * @param tabName the title of the tab to select - * @param name the name of the entry - * @param data value to display - * @param x -coord of the entry starting from 0 - * @param y -coord of the entry starting from 0 - * @return simple widget that can be modified - */ + * Displays a value in Shuffleboard + * + * @param tabName the title of the tab to select + * @param name the name of the entry + * @param data value to display + * @param x -coord of the entry starting from 0 + * @param y -coord of the entry starting from 0 + * @return simple widget that can be modified + */ public static SimpleWidget addData(String tabName, String name, Object data, int x, int y) { return addData(tabName, name, data, x, y, 1, 1); } @@ -101,6 +104,13 @@ public static SimpleWidget addData(String tabName, String name, Supplier * @return simple widget that can be modified */ public static SimpleWidget addData(String tabName, String name, Supplier supply, int x, int y, int width, int height){ + if (x + width > WINDOW_WIDTH || y + height > WINDOW_HEIGHT) { throw new IllegalArgumentException("Widget Position Out of Bounds (" + x + "," + y + ")"); } + for (int i = x; i < x + width; i++) { + for (int j = y; j < y + height; j++) { // TODO is there a better way to fill? + if (entryPositions[i][j]) { throw new IllegalArgumentException("Widget Position Overlapping (" + i + "," + j + ")"); } + entryPositions[i][j] = true; + } + } if(!tabs.containsKey(tabName)) create_tab(tabName); if(tabs.get(tabName).containsKey(name)) { tabs.get(tabName).get(name).m_supply = supply; diff --git a/src/main/java/frc/team3128/subsystems/NAR_PIDSubsystem.java b/src/main/java/frc/team3128/subsystems/NAR_PIDSubsystem.java index 1dfd6f7..ec81322 100644 --- a/src/main/java/frc/team3128/subsystems/NAR_PIDSubsystem.java +++ b/src/main/java/frc/team3128/subsystems/NAR_PIDSubsystem.java @@ -5,6 +5,12 @@ import edu.wpi.first.math.MathUtil; import edu.wpi.first.math.controller.PIDController; +import edu.wpi.first.util.sendable.Sendable; +import edu.wpi.first.util.sendable.SendableRegistry; +import edu.wpi.first.wpilibj.Timer; +import edu.wpi.first.wpilibj.Ultrasonic; +import edu.wpi.first.wpilibj.shuffleboard.SimpleWidget; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; import edu.wpi.first.wpilibj2.command.PIDSubsystem; import edu.wpi.first.wpilibj2.command.SubsystemBase; import frc.team3128.common.utility.NAR_Shuffleboard; @@ -23,6 +29,8 @@ public abstract class NAR_PIDSubsystem extends SubsystemBase { private DoubleSupplier setpoint; private double min, max; + private Timer testTimer = new Timer(); // TODO test - pls delete + /** * Creates a new PIDSubsystem. * @@ -36,6 +44,7 @@ public NAR_PIDSubsystem(PIDController controller, double kS, double kV, double k this.kG_Function = () -> 1; min = Double.NEGATIVE_INFINITY; max = Double.POSITIVE_INFINITY; + testTimer.start(); } /** @@ -59,13 +68,14 @@ public void periodic() { } public void initShuffleboard(double kS, double kV, double kG) { - NAR_Shuffleboard.addComplex(getName(), "PID_Controller", m_controller, 0, 0); + NAR_Shuffleboard.addComplex(getName(), "PID_Controller", this, 0, 0); NAR_Shuffleboard.addData(getName(), "Enabled", ()-> isEnabled(), 1, 0); + NAR_Shuffleboard.addData(getName(), "Measurement", ()-> getMeasurement(), 1, 1); NAR_Shuffleboard.addData(getName(), "Setpoint", ()-> getSetpoint(), 1, 2); - var debugEntry = NAR_Shuffleboard.addData(getName(), "TOGGLE", false, 2, 0).withWidget("Toggle Button"); + var debugEntry = NAR_Shuffleboard.addData(getName(), "TOGGLE", false, 2, 0).withWidget("Toggle Button"); // TODO why use var vs SimpleWidget? debug = ()-> debugEntry.getEntry().getBoolean(false); NAR_Shuffleboard.addData(getName(), "DEBUG", ()-> debug.getAsBoolean(), 2, 1); setpoint = NAR_Shuffleboard.debug(getName(), "Debug_Setpoint", 0, 2,2); @@ -75,9 +85,13 @@ public void initShuffleboard(double kS, double kV, double kG) { this.kG = NAR_Shuffleboard.debug(getName(), "kG", kG, 3, 2); NAR_Shuffleboard.addData(getName(), "atSetpoint", ()-> atSetpoint(), 0, 2); - NAR_Shuffleboard.addComplex(getName(), getName(), this, 4, 0); + NAR_Shuffleboard.addData(getName(), "Test", NAR_Shuffleboard.entryPositions[9][1] == true, 6, 5); // TODO test - pls delete + NAR_Shuffleboard.addData(getName(), "FAIL", ()-> getSetpoint(), 4, 2); } + public String testMethod() { // TODO test - pls delete + return testTimer.toString(); + } /** * Returns the PIDController object controlling the subsystem * From 6ed2bf47bd324accc458df1adbabbd50b31e8a93 Mon Sep 17 00:00:00 2001 From: Arav Chadha Date: Tue, 5 Dec 2023 19:20:29 -0800 Subject: [PATCH 2/4] Fixed sendables Still doesn't work --- simgui.json | 4 +- src/main/java/frc/team3128/Constants.java | 5 +- .../common/utility/NAR_Shuffleboard.java | 109 +++++++++++------- .../team3128/subsystems/NAR_PIDSubsystem.java | 25 ++-- .../subsystems/NAR_ProfiledPIDSubsystem.java | 2 +- .../java/frc/team3128/subsystems/Swerve.java | 15 +-- 6 files changed, 94 insertions(+), 66 deletions(-) diff --git a/simgui.json b/simgui.json index 023c628..c713467 100644 --- a/simgui.json +++ b/simgui.json @@ -5,7 +5,7 @@ "/Shuffleboard/Drivetrain/Drivetrain": "Subsystem", "/Shuffleboard/Drivetrain/Gyro": "Gyro", "/Shuffleboard/Elevator/Elevator": "Subsystem", - "/Shuffleboard/Elevator/PID_Controller": "Subsystem", + "/Shuffleboard/Elevator/PID_Controller": "PIDController", "/Shuffleboard/Elevator/TEST2": "Subsystem", "/Shuffleboard/Field/field": "Field2d", "/Shuffleboard/General/Gyro": "Gyro", @@ -15,7 +15,7 @@ "/Shuffleboard/VisionPID/RCONTROLLER": "PIDController", "/Shuffleboard/VisionPID/XCONTROLLER": "PIDController", "/Shuffleboard/VisionPID/YCONTROLLER": "PIDController", - "/Shuffleboard/Wrist/PID_Controller": "Subsystem", + "/Shuffleboard/Wrist/PID_Controller": "PIDController", "/Shuffleboard/Wrist/TEST2": "Subsystem", "/Shuffleboard/Wrist/Wrist": "Subsystem", "/Shuffleboard/intake/PID Controller": "PIDController", diff --git a/src/main/java/frc/team3128/Constants.java b/src/main/java/frc/team3128/Constants.java index a24dcbe..2fef06e 100644 --- a/src/main/java/frc/team3128/Constants.java +++ b/src/main/java/frc/team3128/Constants.java @@ -26,8 +26,9 @@ public class Constants { public static class ShuffleboardConstants { - public static final int WINDOW_HEIGHT = 10; - public static final int WINDOW_WIDTH = 10; + public static final int WINDOW_WIDTH = 100; + public static final int WINDOW_HEIGHT = 100; + public static final int SHUFFLEBOARD_TABS = 8; } public static class TrajectoryConstants { diff --git a/src/main/java/frc/team3128/common/utility/NAR_Shuffleboard.java b/src/main/java/frc/team3128/common/utility/NAR_Shuffleboard.java index 8006803..a9f91bb 100644 --- a/src/main/java/frc/team3128/common/utility/NAR_Shuffleboard.java +++ b/src/main/java/frc/team3128/common/utility/NAR_Shuffleboard.java @@ -4,14 +4,23 @@ import java.util.function.DoubleSupplier; import java.util.function.Supplier; +import com.ctre.phoenix.sensors.WPI_Pigeon2; + +import edu.wpi.first.math.controller.PIDController; import edu.wpi.first.networktables.GenericEntry; import edu.wpi.first.networktables.NetworkTableEntry; import edu.wpi.first.util.sendable.Sendable; +import edu.wpi.first.wpilibj.interfaces.Gyro; import edu.wpi.first.wpilibj.shuffleboard.BuiltInWidgets; import edu.wpi.first.wpilibj.shuffleboard.ComplexWidget; import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; import edu.wpi.first.wpilibj.shuffleboard.ShuffleboardTab; import edu.wpi.first.wpilibj.shuffleboard.SimpleWidget; +import edu.wpi.first.wpilibj2.command.SubsystemBase; +import frc.team3128.subsystems.Elevator; +import frc.team3128.subsystems.Manipulator; +import frc.team3128.subsystems.NAR_PIDSubsystem; + import static frc.team3128.Constants.ShuffleboardConstants.*; /** @@ -51,8 +60,7 @@ public void update() { } private static HashMap> tabs = new HashMap>(); - public static boolean[][] entryPositions = new boolean[WINDOW_HEIGHT][WINDOW_WIDTH]; // Make private later - + public static HashMap entryPositions = new HashMap(); /** * Creates a new tab entry @@ -61,6 +69,7 @@ public void update() { */ private static void create_tab(String tabName) { tabs.put(tabName, new HashMap()); + entryPositions.put(tabName, new boolean[WINDOW_WIDTH][WINDOW_HEIGHT]); // TODO: added this } /** @@ -104,14 +113,8 @@ public static SimpleWidget addData(String tabName, String name, Supplier * @return simple widget that can be modified */ public static SimpleWidget addData(String tabName, String name, Supplier supply, int x, int y, int width, int height){ - if (x + width > WINDOW_WIDTH || y + height > WINDOW_HEIGHT) { throw new IllegalArgumentException("Widget Position Out of Bounds (" + x + "," + y + ")"); } - for (int i = x; i < x + width; i++) { - for (int j = y; j < y + height; j++) { // TODO is there a better way to fill? - if (entryPositions[i][j]) { throw new IllegalArgumentException("Widget Position Overlapping (" + i + "," + j + ")"); } - entryPositions[i][j] = true; - } - } if(!tabs.containsKey(tabName)) create_tab(tabName); + fillEntryPositions(x,y,width,height, tabName); if(tabs.get(tabName).containsKey(name)) { tabs.get(tabName).get(name).m_supply = supply; return tabs.get(tabName).get(name).m_entry; @@ -122,59 +125,68 @@ public static SimpleWidget addData(String tabName, String name, Supplier } /** - * Displays a value in Shuffleboard - * - * @param tabName the title of the tab to select - * @param name the name of the entry - * @param data value to display - * @param x -coord of the entry starting from 0 - * @param y -coord of the entry starting from 0 - * @param width -of the entry - * @param height -of the entry - * @return simple widget that can be modified - */ - public static SimpleWidget addData(String tabName, String name, Object data, int x, int y, int width, int height) { - if(!tabs.containsKey(tabName)) create_tab(tabName); - if (tabs.get(tabName).containsKey(name)) { - tabs.get(tabName).get(name).m_data.setValue(data); - return tabs.get(tabName).get(name).m_entry; + * Displays a value in Shuffleboard + * + * @param tabName the title of the tab to select + * @param name the name of the entry + * @param data value to display + * @param x -coord of the entry starting from 0 + * @param y -coord of the entry starting from 0 + * @param width -of the entry + * @param height -of the entry + * @return simple widget that can be modified + */ + + public static SimpleWidget addData(String tabName, String name, Object data, int x, int y, int width, int height) { + if(!tabs.containsKey(tabName)) create_tab(tabName); + fillEntryPositions(x,y,width,height,tabName); + if (tabs.get(tabName).containsKey(name)) { + tabs.get(tabName).get(name).m_data.setValue(data); + return tabs.get(tabName).get(name).m_entry; + } + SimpleWidget entry = Shuffleboard.getTab(tabName).add(name,data).withPosition(x, y).withSize(width,height); + tabs.get(tabName).put(name, new entryInfo(entry,null)); + return entry; } - SimpleWidget entry = Shuffleboard.getTab(tabName).add(name,data).withPosition(x, y).withSize(width,height); - tabs.get(tabName).put(name, new entryInfo(entry,null)); - return entry; -} /** - * Displays complex values, like subsystems and command, works on all classes that extend sendable + * Displays sendable values, like subsystems and command, works on all classes that extend sendable * * @param tabName the title of the tab to select * @param name the name of the entry - * @param data complex value to display + * @param data sendable value to display * @param x x-coord of the entry * @param y y-coord of the entry - * @return complex widget that can be modified + * @return sendable widget that can be modified */ - public static ComplexWidget addComplex(String tabName, String name, Sendable data, int x, int y) { - try { - return Shuffleboard.getTab(tabName).add(name, data).withPosition(x,y); - } - catch(Exception e) { - return null; - } + public static ComplexWidget addSendable(String tabName, String name, Sendable data, int x, int y) { + if (data instanceof SubsystemBase) return addSendable(tabName, name, data, x, y, 2, 1); + if (data instanceof PIDController) return addSendable(tabName, name, data, x, y, 1, 2); + if (data instanceof WPI_Pigeon2) return addSendable(tabName, name, data, x, y, 2, 2); + return addSendable(tabName, name, data, x, y, 1, 1); // Default width and height } /** - * Displays complex values, like subsystems and command, works on all classes that extend sendable + * Displays sendable values, like subsystems and command, works on all classes that extend sendable * * @param tabName the title of the tab to select * @param name the name of the entry - * @param data complex value to display + * @param data sendable value to display * @param x x-coord of the entry * @param y y-coord of the entry - * @return complex widget that can be modified + * @return sendable widget that can be modified */ - public static ComplexWidget addComplex(String tabName, String name, Sendable data, int x, int y, int width, int height) { - return addComplex(tabName, name, data, x, y).withSize(width,height); + public static ComplexWidget addSendable(String tabName, String name, Sendable data, int x, int y, int width, int height) { + try { + if(!tabs.containsKey(tabName)) create_tab(tabName); + fillEntryPositions(x, y, width, height, tabName); + + return Shuffleboard.getTab(tabName).add(name, data).withPosition(x,y).withSize(width, height); + } + catch(Exception e) { + return null; + } + // return addSendable(tabName, name, data, x, y).withSize(width,height); } /** @@ -246,4 +258,13 @@ public static void update() { } } + private static void fillEntryPositions(int x, int y, int width, int height, String tabName) { + if (x + width > WINDOW_WIDTH || y + height > WINDOW_HEIGHT) { throw new IllegalArgumentException("Widget Position Out of Bounds (" + x + "," + y + ") at Tab: " + tabName); } + for (int i = x; i < x + width; i++) { + for (int j = y; j < y + height; j++) { + if (entryPositions.get(tabName)[i][j]) { throw new IllegalArgumentException("Widget Position Overlapping (" + i + "," + j + ") at Tab: " + tabName); } + entryPositions.get(tabName)[i][j] = true; + } + } + } } \ No newline at end of file diff --git a/src/main/java/frc/team3128/subsystems/NAR_PIDSubsystem.java b/src/main/java/frc/team3128/subsystems/NAR_PIDSubsystem.java index ec81322..ecf625f 100644 --- a/src/main/java/frc/team3128/subsystems/NAR_PIDSubsystem.java +++ b/src/main/java/frc/team3128/subsystems/NAR_PIDSubsystem.java @@ -18,7 +18,7 @@ /** * A subsystem based off of {@link PIDSubsystem} * @since 2023 CHARGED UP - * @author Mason Lam + * @author Mason Lam, Arav Chadha, Peter Ma */ public abstract class NAR_PIDSubsystem extends SubsystemBase { protected final PIDController m_controller; @@ -29,8 +29,6 @@ public abstract class NAR_PIDSubsystem extends SubsystemBase { private DoubleSupplier setpoint; private double min, max; - private Timer testTimer = new Timer(); // TODO test - pls delete - /** * Creates a new PIDSubsystem. * @@ -44,7 +42,6 @@ public NAR_PIDSubsystem(PIDController controller, double kS, double kV, double k this.kG_Function = () -> 1; min = Double.NEGATIVE_INFINITY; max = Double.POSITIVE_INFINITY; - testTimer.start(); } /** @@ -68,7 +65,7 @@ public void periodic() { } public void initShuffleboard(double kS, double kV, double kG) { - NAR_Shuffleboard.addComplex(getName(), "PID_Controller", this, 0, 0); + NAR_Shuffleboard.addSendable(getName(), "PID_Controller", m_controller, 0, 0); NAR_Shuffleboard.addData(getName(), "Enabled", ()-> isEnabled(), 1, 0); @@ -85,18 +82,26 @@ public void initShuffleboard(double kS, double kV, double kG) { this.kG = NAR_Shuffleboard.debug(getName(), "kG", kG, 3, 2); NAR_Shuffleboard.addData(getName(), "atSetpoint", ()-> atSetpoint(), 0, 2); - NAR_Shuffleboard.addData(getName(), "Test", NAR_Shuffleboard.entryPositions[9][1] == true, 6, 5); // TODO test - pls delete - NAR_Shuffleboard.addData(getName(), "FAIL", ()-> getSetpoint(), 4, 2); + NAR_Shuffleboard.addData(getName(), "TestSendable", NAR_Shuffleboard.entryPositions.get(getName())[0][0] == true, 6, 3); // TODO test - pls delete + NAR_Shuffleboard.addData(getName(), "TestData", NAR_Shuffleboard.entryPositions.get(getName())[1][0] == true, 7, 3); // TODO test - pls delete + NAR_Shuffleboard.addSendable(getName(), getName(), this, 4, 0); + + // Print entryPositions: + if (getName().equals("Wrist")) { // To ensure this check is done only once + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 6; j++) { + NAR_Shuffleboard.addData("TESTER", "X: " + i + " Y: " + j, NAR_Shuffleboard.entryPositions.get("Drivetrain")[i][j] == true, i, j); + } + } + } } - public String testMethod() { // TODO test - pls delete - return testTimer.toString(); - } /** * Returns the PIDController object controlling the subsystem * * @return The PIDController */ + public PIDController getController() { return m_controller; } diff --git a/src/main/java/frc/team3128/subsystems/NAR_ProfiledPIDSubsystem.java b/src/main/java/frc/team3128/subsystems/NAR_ProfiledPIDSubsystem.java index b928232..b92a1c7 100644 --- a/src/main/java/frc/team3128/subsystems/NAR_ProfiledPIDSubsystem.java +++ b/src/main/java/frc/team3128/subsystems/NAR_ProfiledPIDSubsystem.java @@ -63,7 +63,7 @@ public void periodic() { } private void initShuffleboard(double kS, double kV, double kG) { - NAR_Shuffleboard.addComplex(getName(), "PID_Controller", m_controller, 0, 0); + NAR_Shuffleboard.addSendable(getName(), "PID_Controller", m_controller, 0, 0); NAR_Shuffleboard.addData(getName(), "Enabled", ()-> isEnabled(), 1, 0); NAR_Shuffleboard.addData(getName(), "Measurement", ()-> getMeasurement(), 1, 1); diff --git a/src/main/java/frc/team3128/subsystems/Swerve.java b/src/main/java/frc/team3128/subsystems/Swerve.java index c850b14..a1a688a 100644 --- a/src/main/java/frc/team3128/subsystems/Swerve.java +++ b/src/main/java/frc/team3128/subsystems/Swerve.java @@ -101,24 +101,25 @@ public void setBrakeMode(boolean isBrake) { } } - public void initShuffleboard() { + public void initShuffleboard() { // hasTarget, speed, acceleration, Single Station // General Tab - NAR_Shuffleboard.addComplex("General","Gyro",gyro,7,2,2,2);//.withWidget("Gyro"); - NAR_Shuffleboard.addData("General","Heading",this::getHeading,1,2); + NAR_Shuffleboard.addSendable("General","Gyro",gyro,7,2,2,2);//.withWidget("Gyro"); + NAR_Shuffleboard.addData("General","Heading",this::getHeading,0,0); // // Drivetrain Tab NAR_Shuffleboard.addData("Drivetrain","Pose",() -> (getPose().toString()),2,0,4,1); - NAR_Shuffleboard.addComplex("Drivetrain","Gyro",gyro,3,1,2,2);//.withWidget("Gyro"); + NAR_Shuffleboard.addSendable("Drivetrain","Gyro",gyro,3,2,2,2);//.withWidget("Gyro"); NAR_Shuffleboard.addData("Drivetrain","Yaw",this::getYaw,4,1); NAR_Shuffleboard.addData("Drivetrain","Pitch",this::getPitch,5,1); NAR_Shuffleboard.addData("Drivetrain", "Roll", this::getRoll, 0, 2); - NAR_Shuffleboard.addData("Drivetrain","Heading/Angle",this::getHeading,6,1); - NAR_Shuffleboard.addComplex("Drivetrain","Drivetrain", this,0,0); + // NAR_Shuffleboard.addData("Drivetrain","Heading/Angle",false,6,1); + NAR_Shuffleboard.addData("Drivetrain","Heading",this::getHeading,6,1); + NAR_Shuffleboard.addSendable("Drivetrain","Drivetrain", this,0,0); NAR_Shuffleboard.addData("Drivetrain", "ENABLE", ()-> CmdManager.ENABLE, 0, 1); NAR_Shuffleboard.addData("Drivetrain", "Single Station", ()-> CmdManager.SINGLE_STATION, 0, 3); NAR_Shuffleboard.addData("Drivetrain", "Speed", ()-> speed, 2, 1); NAR_Shuffleboard.addData("Drivetrain", "Acceleration", ()-> acceleration, 3, 1); } - + public Pose2d getPose() { return new Pose2d(estimatedPose.getTranslation(), getGyroRotation2d()); } From f59d359522c32db1a48b882aa263819ced21dfc1 Mon Sep 17 00:00:00 2001 From: Arav Chadha <97276472+AravCGitHub@users.noreply.github.com> Date: Mon, 8 Jan 2024 16:18:15 -0800 Subject: [PATCH 3/4] Changes --- .../java/frc/team3128/RobotContainer.java | 1 - .../frc/team3128/autonomous/AutoPrograms.java | 5 +++ .../common/utility/NAR_Shuffleboard.java | 37 ++++++++++++++++++- .../frc/team3128/subsystems/Manipulator.java | 15 ++++++-- .../team3128/subsystems/NAR_PIDSubsystem.java | 18 +++++---- 5 files changed, 64 insertions(+), 12 deletions(-) diff --git a/src/main/java/frc/team3128/RobotContainer.java b/src/main/java/frc/team3128/RobotContainer.java index 1179974..f211122 100644 --- a/src/main/java/frc/team3128/RobotContainer.java +++ b/src/main/java/frc/team3128/RobotContainer.java @@ -179,7 +179,6 @@ private void initDashboard() { swerve.initShuffleboard(); Vision.getInstance().initShuffleboard(); - NarwhalDashboard.startServer(); } diff --git a/src/main/java/frc/team3128/autonomous/AutoPrograms.java b/src/main/java/frc/team3128/autonomous/AutoPrograms.java index 6c563ab..f7e4185 100644 --- a/src/main/java/frc/team3128/autonomous/AutoPrograms.java +++ b/src/main/java/frc/team3128/autonomous/AutoPrograms.java @@ -7,8 +7,12 @@ import frc.team3128.PositionConstants.Position; import frc.team3128.commands.CmdAutoBalance; import frc.team3128.common.narwhaldashboard.NarwhalDashboard; +import frc.team3128.common.utility.NAR_Shuffleboard; + import static frc.team3128.commands.CmdManager.*; +import java.util.function.DoubleSupplier; + /** * Class to store information about autonomous routines. * @author Daniel Wang, Mason Lam @@ -35,6 +39,7 @@ private void initAutoSelector() { "scuffedClimb" }; NarwhalDashboard.addAutos(autoStrings); + NAR_Shuffleboard.addAutos(autoStrings); } public Command getAutonomousCommand() { diff --git a/src/main/java/frc/team3128/common/utility/NAR_Shuffleboard.java b/src/main/java/frc/team3128/common/utility/NAR_Shuffleboard.java index a9f91bb..2318b6c 100644 --- a/src/main/java/frc/team3128/common/utility/NAR_Shuffleboard.java +++ b/src/main/java/frc/team3128/common/utility/NAR_Shuffleboard.java @@ -1,6 +1,8 @@ package frc.team3128.common.utility; +import java.util.Arrays; import java.util.HashMap; +import java.util.Map; import java.util.function.DoubleSupplier; import java.util.function.Supplier; @@ -11,9 +13,11 @@ import edu.wpi.first.networktables.NetworkTableEntry; import edu.wpi.first.util.sendable.Sendable; import edu.wpi.first.wpilibj.interfaces.Gyro; +import edu.wpi.first.wpilibj.shuffleboard.BuiltInLayouts; import edu.wpi.first.wpilibj.shuffleboard.BuiltInWidgets; import edu.wpi.first.wpilibj.shuffleboard.ComplexWidget; import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; +import edu.wpi.first.wpilibj.shuffleboard.ShuffleboardLayout; import edu.wpi.first.wpilibj.shuffleboard.ShuffleboardTab; import edu.wpi.first.wpilibj.shuffleboard.SimpleWidget; import edu.wpi.first.wpilibj2.command.SubsystemBase; @@ -180,7 +184,6 @@ public static ComplexWidget addSendable(String tabName, String name, Sendable da try { if(!tabs.containsKey(tabName)) create_tab(tabName); fillEntryPositions(x, y, width, height, tabName); - return Shuffleboard.getTab(tabName).add(name, data).withPosition(x,y).withSize(width, height); } catch(Exception e) { @@ -189,6 +192,38 @@ public static ComplexWidget addSendable(String tabName, String name, Sendable da // return addSendable(tabName, name, data, x, y).withSize(width,height); } + public static ComplexWidget addVideoStream(String tabName, String name, String cameraName, String URL, int x, int y, int width, int height) { + try { + if (!tabs.containsKey(tabName)) create_tab(tabName); + fillEntryPositions(x, y, width, height, tabName); + + ComplexWidget videoStream = Shuffleboard.getTab(tabName) + .addCamera(name, cameraName, URL) + .withProperties(Map.of("showControls", false)) + .withPosition(x, y) + .withSize(width, height); + return videoStream; + } + catch(Exception e) { + return null; + } + } + + public static void addAutos(String[] autoNames) { + if (!tabs.containsKey("Autos")) create_tab("Autos"); + ShuffleboardLayout autoLayout = Shuffleboard.getTab("Autos") + .getLayout("Auto Names", BuiltInLayouts.kList) + .withSize(2,4); + // .withProperties(Map.of("Label position", "HIDDEN")); + for (int i = 1; i <= autoNames.length; i++) { + autoLayout.add(""+i, autoNames[i-1]); // Shuffleboard doesn't display elements in order of String[] names so we can't use an auto name's index to reference it + } + // DoubleSupplier autoNumber = NAR_Shuffleboard.debug("Autos", "Selector", -1, 3, 0); + // var autoEntry = NAR_Shuffleboard.addData("Autos", "TOGGLE", false, 2, 0).withWidget("Toggle Button"); // TODO why use var vs SimpleWidget? + // debug = ()-> debugEntry.getEntry().getBoolean(false); + // NAR_Shuffleboard.addData(getName(), "DEBUG", ()-> debug.getAsBoolean(), 2, 1); + } + /** * Creates a debug entry, allows user to edit variable from Shuffleboard * diff --git a/src/main/java/frc/team3128/subsystems/Manipulator.java b/src/main/java/frc/team3128/subsystems/Manipulator.java index b2ef096..e173b86 100644 --- a/src/main/java/frc/team3128/subsystems/Manipulator.java +++ b/src/main/java/frc/team3128/subsystems/Manipulator.java @@ -72,8 +72,17 @@ public double getCurrent(){ } public void initShuffleboard() { - NAR_Shuffleboard.addData("Manipulator", "Manip current", () -> getCurrent(), 0, 1); - NAR_Shuffleboard.addData("Manipulator", "get", () -> m_roller.getMotorOutputPercent(), 0, 3); - NAR_Shuffleboard.addData("Manipulator", "ObjectPresent", ()-> hasObjectPresent(), 1, 1); + NAR_Shuffleboard.addData("Manipulator", "Manip current", () -> getCurrent(), 0, 0); + NAR_Shuffleboard.addData("Manipulator", "get", () -> m_roller.getMotorOutputPercent(), 1, 0); + NAR_Shuffleboard.addData("Manipulator", "ObjectPresent", ()-> hasObjectPresent(), 2, 0); + NAR_Shuffleboard.addVideoStream("Manipulator", "VideoTest", "Gua", "mjpg:http://10.31.28.71:5800/", 0, 1, 3, 3); + + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 6; j++) { + final int row = i; + final int col = j; + NAR_Shuffleboard.addData("TESTER", "X: " + i + " Y: " + j, ()-> NAR_Shuffleboard.entryPositions.get("Manipulator")[row][col] == true, i, j); + } + } } } diff --git a/src/main/java/frc/team3128/subsystems/NAR_PIDSubsystem.java b/src/main/java/frc/team3128/subsystems/NAR_PIDSubsystem.java index ecf625f..23907ce 100644 --- a/src/main/java/frc/team3128/subsystems/NAR_PIDSubsystem.java +++ b/src/main/java/frc/team3128/subsystems/NAR_PIDSubsystem.java @@ -87,13 +87,17 @@ public void initShuffleboard(double kS, double kV, double kG) { NAR_Shuffleboard.addSendable(getName(), getName(), this, 4, 0); // Print entryPositions: - if (getName().equals("Wrist")) { // To ensure this check is done only once - for (int i = 0; i < 8; i++) { - for (int j = 0; j < 6; j++) { - NAR_Shuffleboard.addData("TESTER", "X: " + i + " Y: " + j, NAR_Shuffleboard.entryPositions.get("Drivetrain")[i][j] == true, i, j); - } - } - } + // if (getName().equals("Wrist")) { // To ensure this check is done only once + // for (int i = 0; i < 8; i++) { + // for (int j = 0; j < 6; j++) { + // final int row = i; + // final int col = j; + // NAR_Shuffleboard.addData("TESTER", "X: " + i + " Y: " + j, ()-> NAR_Shuffleboard.entryPositions.get("Manipulator")[row][col] == true, i, j); + // } + // } + // } + + } /** From 641e590cac4fd90ae45f5d14254d88c20e82acd9 Mon Sep 17 00:00:00 2001 From: Arav Chadha <97276472+AravCGitHub@users.noreply.github.com> Date: Mon, 15 Jan 2024 13:50:37 -0800 Subject: [PATCH 4/4] Shuffleboard auto selection --- src/main/java/frc/team3128/Constants.java | 6 - .../frc/team3128/autonomous/AutoPrograms.java | 5 +- .../common/utility/NAR_Shuffleboard.java | 272 ++++++++++++------ .../frc/team3128/subsystems/Manipulator.java | 14 +- .../team3128/subsystems/NAR_PIDSubsystem.java | 15 +- 5 files changed, 192 insertions(+), 120 deletions(-) diff --git a/src/main/java/frc/team3128/Constants.java b/src/main/java/frc/team3128/Constants.java index 2fef06e..0774c4d 100644 --- a/src/main/java/frc/team3128/Constants.java +++ b/src/main/java/frc/team3128/Constants.java @@ -25,12 +25,6 @@ public class Constants { - public static class ShuffleboardConstants { - public static final int WINDOW_WIDTH = 100; - public static final int WINDOW_HEIGHT = 100; - public static final int SHUFFLEBOARD_TABS = 8; - } - public static class TrajectoryConstants { public static final Rotation2d HEADING = Rotation2d.fromDegrees(180); diff --git a/src/main/java/frc/team3128/autonomous/AutoPrograms.java b/src/main/java/frc/team3128/autonomous/AutoPrograms.java index f7e4185..8d4fa53 100644 --- a/src/main/java/frc/team3128/autonomous/AutoPrograms.java +++ b/src/main/java/frc/team3128/autonomous/AutoPrograms.java @@ -11,8 +11,6 @@ import static frc.team3128.commands.CmdManager.*; -import java.util.function.DoubleSupplier; - /** * Class to store information about autonomous routines. * @author Daniel Wang, Mason Lam @@ -43,7 +41,8 @@ private void initAutoSelector() { } public Command getAutonomousCommand() { - String selectedAutoName = NarwhalDashboard.getSelectedAutoName(); + String selectedAutoName = NarwhalDashboard.getSelectedAutoName(); // Priority to NarwhalDashboard + if (selectedAutoName == null) { selectedAutoName = NAR_Shuffleboard.getSelectedAutoName(); } final Command autoCommand; if (selectedAutoName == null) { diff --git a/src/main/java/frc/team3128/common/utility/NAR_Shuffleboard.java b/src/main/java/frc/team3128/common/utility/NAR_Shuffleboard.java index 2318b6c..571a0b1 100644 --- a/src/main/java/frc/team3128/common/utility/NAR_Shuffleboard.java +++ b/src/main/java/frc/team3128/common/utility/NAR_Shuffleboard.java @@ -1,6 +1,5 @@ package frc.team3128.common.utility; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.function.DoubleSupplier; @@ -10,81 +9,115 @@ import edu.wpi.first.math.controller.PIDController; import edu.wpi.first.networktables.GenericEntry; -import edu.wpi.first.networktables.NetworkTableEntry; import edu.wpi.first.util.sendable.Sendable; -import edu.wpi.first.wpilibj.interfaces.Gyro; import edu.wpi.first.wpilibj.shuffleboard.BuiltInLayouts; -import edu.wpi.first.wpilibj.shuffleboard.BuiltInWidgets; import edu.wpi.first.wpilibj.shuffleboard.ComplexWidget; import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; import edu.wpi.first.wpilibj.shuffleboard.ShuffleboardLayout; import edu.wpi.first.wpilibj.shuffleboard.ShuffleboardTab; import edu.wpi.first.wpilibj.shuffleboard.SimpleWidget; import edu.wpi.first.wpilibj2.command.SubsystemBase; -import frc.team3128.subsystems.Elevator; -import frc.team3128.subsystems.Manipulator; -import frc.team3128.subsystems.NAR_PIDSubsystem; - -import static frc.team3128.Constants.ShuffleboardConstants.*; /** * Wrapper for {@link Shuffleboard} * @since 2022 RAPID REACT - * @author Mason Lam + * @author Mason Lam, Arav Chadha, Peter Ma */ public class NAR_Shuffleboard { /** * Storage class for NAR_Shuffleboard */ - private static class entryInfo { + private static class widgetInfo { - private GenericEntry m_data; - + private SimpleWidget m_widget; private Supplier m_supply; - - private SimpleWidget m_entry; - + private GenericEntry m_entry; + /** - * Creates a new entry Info + * Creates a new widgetInfo * - * @param entry Widget where the entry + * @param widget widget containing the entry * @param supply supplier updating the entry */ - public entryInfo(SimpleWidget entry, Supplier supply){ + public widgetInfo(SimpleWidget widget, Supplier supply){ + m_widget = widget; m_supply = supply; - m_entry = entry; - m_data = entry.getEntry(); + m_entry = widget.getEntry(); } public void update() { if(m_supply == null) return; - m_data.setValue(m_supply.get()); + m_entry.setValue(m_supply.get()); } } - private static HashMap> tabs = new HashMap>(); - public static HashMap entryPositions = new HashMap(); + private static final int WINDOW_WIDTH = 8; + private static final int WINDOW_HEIGHT = 4; + + private static HashMap> tabs = new HashMap>(); + private static HashMap widgetPositions = new HashMap(); + private static SimpleWidget[] autoWidgets; + private static String[] autoNames; + private static String selectedAutoName; + private static int prevAutoIndex; + /** - * Creates a new tab entry + * Creates a new tab * * @param tabName the title of the new tab */ private static void create_tab(String tabName) { - tabs.put(tabName, new HashMap()); - entryPositions.put(tabName, new boolean[WINDOW_WIDTH][WINDOW_HEIGHT]); // TODO: added this + tabs.put(tabName, new HashMap()); + widgetPositions.put(tabName, new boolean[WINDOW_WIDTH][WINDOW_HEIGHT]); // TODO: added this + } + + /** + * Displays a value in Shuffleboard (Only used for autofill) + * + * @param tabName the title of the tab to select + * @param name the name of the widget + * @param data the value to display + * @return SimpleWidget that can be modified + */ + public static SimpleWidget addData(String tabName, String name, Object data) { + for (int i = 0; i < WINDOW_HEIGHT; i++) { + for (int j = 0; j < WINDOW_WIDTH; j++) { + if (!widgetPositions.get(tabName)[j][i]) return addData(tabName, name, data, j, i, 1, 1); + widgetPositions.get(tabName)[j][i] = true; + } + } + return addData(tabName, name, data, 0, 0, 1, 1); + } + + /** + * Displays a value in Shuffleboard (Only used for autofill) + * + * @param tabName the title of the tab to select + * @param name the name of the widget + * @param supply the value to display + * @return SimpleWidget that can be modified + */ + public static SimpleWidget addData(String tabName, String name, Supplier supply) { + for (int i = 0; i < WINDOW_HEIGHT; i++) { + for (int j = 0; j < WINDOW_WIDTH; j++) { + if (!widgetPositions.get(tabName)[j][i]) return addData(tabName, name, supply, j, i, 1, 1); + widgetPositions.get(tabName)[j][i] = true; + } + } + return addData(tabName, name, supply, 0, 0, 1, 1); } /** * Displays a value in Shuffleboard * * @param tabName the title of the tab to select - * @param name the name of the entry - * @param data value to display - * @param x -coord of the entry starting from 0 - * @param y -coord of the entry starting from 0 - * @return simple widget that can be modified + * @param name the name of the widget + * @param data the value to display + * @param x coord of the widget starting from 0 + * @param y coord of the widget starting from 0 + * @return SimpleWidget that can be modified */ public static SimpleWidget addData(String tabName, String name, Object data, int x, int y) { return addData(tabName, name, data, x, y, 1, 1); @@ -94,11 +127,11 @@ public static SimpleWidget addData(String tabName, String name, Object data, int * Displays an updating value in Shuffleboard * * @param tabName the title of the tab to select - * @param name the name of the entry + * @param name the name of the widget * @param supply object supplier to constantly update value - * @param x -coord of the entry starting from 0 - * @param y -coord of the entry starting from 0 - * @return simple widget that can be modified + * @param x coord of the widget starting from 0 + * @param y coord of the widget starting from 0 + * @return SimpleWidget that can be modified */ public static SimpleWidget addData(String tabName, String name, Supplier supply, int x, int y) { return addData(tabName, name, supply, x, y, 1, 1); @@ -108,12 +141,12 @@ public static SimpleWidget addData(String tabName, String name, Supplier * Displays an updating value in Shuffleboard * * @param tabName the title of the tab to select - * @param name the name of the entry + * @param name the name of the widget * @param supply object supplier to constantly update value - * @param x -coord of the entry starting from 0 - * @param y -coord of the entry starting from 0 - * @param width -of the entry - * @param height -of the entry + * @param x -coord of the widget starting from 0 + * @param y -coord of the widget starting from 0 + * @param width -of the widget + * @param height -of the widget * @return simple widget that can be modified */ public static SimpleWidget addData(String tabName, String name, Supplier supply, int x, int y, int width, int height){ @@ -121,46 +154,45 @@ public static SimpleWidget addData(String tabName, String name, Supplier fillEntryPositions(x,y,width,height, tabName); if(tabs.get(tabName).containsKey(name)) { tabs.get(tabName).get(name).m_supply = supply; - return tabs.get(tabName).get(name).m_entry; + return tabs.get(tabName).get(name).m_widget; } - SimpleWidget entry = Shuffleboard.getTab(tabName).add(name,supply.get()).withPosition(x, y).withSize(width, height); - tabs.get(tabName).put(name, new entryInfo(entry,supply)); - return entry; + SimpleWidget widget = Shuffleboard.getTab(tabName).add(name,supply.get()).withPosition(x, y).withSize(width, height); + tabs.get(tabName).put(name, new widgetInfo(widget,supply)); + return widget; } /** * Displays a value in Shuffleboard * * @param tabName the title of the tab to select - * @param name the name of the entry + * @param name the name of the widget * @param data value to display - * @param x -coord of the entry starting from 0 - * @param y -coord of the entry starting from 0 - * @param width -of the entry - * @param height -of the entry + * @param x -coord of the widget starting from 0 + * @param y -coord of the widget starting from 0 + * @param width -of the widget + * @param height -of the widget * @return simple widget that can be modified */ - public static SimpleWidget addData(String tabName, String name, Object data, int x, int y, int width, int height) { if(!tabs.containsKey(tabName)) create_tab(tabName); fillEntryPositions(x,y,width,height,tabName); if (tabs.get(tabName).containsKey(name)) { - tabs.get(tabName).get(name).m_data.setValue(data); - return tabs.get(tabName).get(name).m_entry; + tabs.get(tabName).get(name).m_entry.setValue(data); + return tabs.get(tabName).get(name).m_widget; } - SimpleWidget entry = Shuffleboard.getTab(tabName).add(name,data).withPosition(x, y).withSize(width,height); - tabs.get(tabName).put(name, new entryInfo(entry,null)); - return entry; + SimpleWidget widget = Shuffleboard.getTab(tabName).add(name,data).withPosition(x, y).withSize(width,height); + tabs.get(tabName).put(name, new widgetInfo(widget,null)); + return widget; } /** * Displays sendable values, like subsystems and command, works on all classes that extend sendable * * @param tabName the title of the tab to select - * @param name the name of the entry + * @param name the name of the widget * @param data sendable value to display - * @param x x-coord of the entry - * @param y y-coord of the entry + * @param x x-coord of the widget + * @param y y-coord of the widget * @return sendable widget that can be modified */ public static ComplexWidget addSendable(String tabName, String name, Sendable data, int x, int y) { @@ -174,10 +206,10 @@ public static ComplexWidget addSendable(String tabName, String name, Sendable da * Displays sendable values, like subsystems and command, works on all classes that extend sendable * * @param tabName the title of the tab to select - * @param name the name of the entry + * @param name the name of the widget * @param data sendable value to display - * @param x x-coord of the entry - * @param y y-coord of the entry + * @param x x-coord of the widget + * @param y y-coord of the widget * @return sendable widget that can be modified */ public static ComplexWidget addSendable(String tabName, String name, Sendable data, int x, int y, int width, int height) { @@ -189,9 +221,21 @@ public static ComplexWidget addSendable(String tabName, String name, Sendable da catch(Exception e) { return null; } - // return addSendable(tabName, name, data, x, y).withSize(width,height); } + /** + * Adds video stream to shuffleboard + * + * @param tabName the title of the tab to select + * @param name the name of the widget + * @param cameraName sendable value to display + * @param URL x-coord of the widget + * @param x coord of the widget + * @param y coord of the widget + * @param width y-coord of the widget + * @param height y-coord of the widget + * @return sendable widget that can be modified + */ public static ComplexWidget addVideoStream(String tabName, String name, String cameraName, String URL, int x, int y, int width, int height) { try { if (!tabs.containsKey(tabName)) create_tab(tabName); @@ -209,30 +253,67 @@ public static ComplexWidget addVideoStream(String tabName, String name, String c } } - public static void addAutos(String[] autoNames) { + /** + * Displays auto paths on Shuffleboard and updates selected auto + * + * @param autos a String array with all auto names + */ + public static void addAutos(String[] autos) { + autoNames = autos; if (!tabs.containsKey("Autos")) create_tab("Autos"); + + autoWidgets = new SimpleWidget[autoNames.length]; ShuffleboardLayout autoLayout = Shuffleboard.getTab("Autos") .getLayout("Auto Names", BuiltInLayouts.kList) - .withSize(2,4); - // .withProperties(Map.of("Label position", "HIDDEN")); - for (int i = 1; i <= autoNames.length; i++) { - autoLayout.add(""+i, autoNames[i-1]); // Shuffleboard doesn't display elements in order of String[] names so we can't use an auto name's index to reference it + .withSize(2, 4) + .withProperties(Map.of("Label position", "HIDDEN")); + + for (int i = 0; i < autoNames.length; i++) { + autoWidgets[i] = autoLayout.add(autoNames[i], false).withWidget("Toggle Button"); + } + addData("Autos", "Auto", ()-> (updateAutoSelection() == null) ? "null" : updateAutoSelection(), 2, 0); // Continuously runs updateAutoSelection() + } + + /** + * Updates selectedAutoName and shuffleboard auto selection layout + * + * @param autos a String array with all auto names + */ + private static String updateAutoSelection() { + boolean isSelected = false; + for (int i = 0; i < autoNames.length; i++) { + if (autoWidgets[i].getEntry().getBoolean(false)) { + isSelected = true; + if (i == prevAutoIndex) { continue; } + if (prevAutoIndex != -1) { autoWidgets[prevAutoIndex].getEntry().setBoolean(false); } + prevAutoIndex = i; + selectedAutoName = autoNames[i]; + } + } + if (!isSelected) { + selectedAutoName = null; + prevAutoIndex = -1; } - // DoubleSupplier autoNumber = NAR_Shuffleboard.debug("Autos", "Selector", -1, 3, 0); - // var autoEntry = NAR_Shuffleboard.addData("Autos", "TOGGLE", false, 2, 0).withWidget("Toggle Button"); // TODO why use var vs SimpleWidget? - // debug = ()-> debugEntry.getEntry().getBoolean(false); - // NAR_Shuffleboard.addData(getName(), "DEBUG", ()-> debug.getAsBoolean(), 2, 1); + return selectedAutoName; } /** - * Creates a debug entry, allows user to edit variable from Shuffleboard + * Gets selectedAutoName + * + */ + public static String getSelectedAutoName() { + return selectedAutoName; + } + + /** + * Creates a debug widget, allows user to edit variable from Shuffleboard * * @param tabName the title of the tab to select - * @param name the name of the entry - * @param Default starting value for the entry - * @param x x-coord of the entry - * @param y y-coord of the entry - * @return DoubleSupplier containing the value in the entry + * @param name the name of the widget + * @param Default starting value for the widget + * @param x x-coord of the widget + * @param y y-coord of the widget + * @return DoubleSupplier containing the value in the widget */ public static DoubleSupplier debug(String tabName, String name, double Default, int x, int y) { if(!tabs.containsKey(tabName)){ @@ -246,8 +327,8 @@ public static DoubleSupplier debug(String tabName, String name, double Default, * Creates a quick PID Tuning setup * * @param tabName the title of the tab to select - * @param name the name of the entry - * @param prefix String that goes before PID entry names + * @param name the name of the widget + * @param prefix String that goes before PID widget names * @return HashMap with keys "KF","KP","KI","KD", and "SETPOINT" */ public static HashMap PID_Setup(String tabName, String prefix) { @@ -261,29 +342,29 @@ public static HashMap PID_Setup(String tabName, String pr } /** - * Get the value from an entry + * Get the value from an widget * * @param tabName the title of the tab to select - * @param name the name of the entry - * @return Object stored in the entry + * @param name the name of the widget + * @return Object stored in the widget */ public static Object getValue(String tabName, String name){ - return tabs.get(tabName).get(name).m_data.get().getValue(); + return tabs.get(tabName).get(name).m_entry.get().getValue(); } /** - * Get the Simple Widget object from an entry + * Get the Simple Widget object from an widget * * @param tabName the title of the tab to select - * @param name the name of the entry - * @return SimpleWidget stored in the entry + * @param name the name of the widget + * @return SimpleWidget stored in the widget */ public static SimpleWidget getEntry(String tabName,String name) { - return tabs.get(tabName).get(name).m_entry; + return tabs.get(tabName).get(name).m_widget; } /** - * Updates every entry + * Updates every widget */ public static void update() { for(String i : tabs.keySet()){ @@ -293,12 +374,21 @@ public static void update() { } } + /** + * Fills widget position array for a given tab + * + * @param x x-coord of the widget + * @param y y-coord of the widget + * @param width width of the widget + * @param height height of the widget + * @param tabName the title of the tab to select + */ private static void fillEntryPositions(int x, int y, int width, int height, String tabName) { if (x + width > WINDOW_WIDTH || y + height > WINDOW_HEIGHT) { throw new IllegalArgumentException("Widget Position Out of Bounds (" + x + "," + y + ") at Tab: " + tabName); } for (int i = x; i < x + width; i++) { for (int j = y; j < y + height; j++) { - if (entryPositions.get(tabName)[i][j]) { throw new IllegalArgumentException("Widget Position Overlapping (" + i + "," + j + ") at Tab: " + tabName); } - entryPositions.get(tabName)[i][j] = true; + if (widgetPositions.get(tabName)[i][j]) { throw new IllegalArgumentException("Widget Position Overlapping (" + i + "," + j + ") at Tab: " + tabName); } + widgetPositions.get(tabName)[i][j] = true; } } } diff --git a/src/main/java/frc/team3128/subsystems/Manipulator.java b/src/main/java/frc/team3128/subsystems/Manipulator.java index e173b86..47f060c 100644 --- a/src/main/java/frc/team3128/subsystems/Manipulator.java +++ b/src/main/java/frc/team3128/subsystems/Manipulator.java @@ -77,12 +77,12 @@ public void initShuffleboard() { NAR_Shuffleboard.addData("Manipulator", "ObjectPresent", ()-> hasObjectPresent(), 2, 0); NAR_Shuffleboard.addVideoStream("Manipulator", "VideoTest", "Gua", "mjpg:http://10.31.28.71:5800/", 0, 1, 3, 3); - for (int i = 0; i < 8; i++) { - for (int j = 0; j < 6; j++) { - final int row = i; - final int col = j; - NAR_Shuffleboard.addData("TESTER", "X: " + i + " Y: " + j, ()-> NAR_Shuffleboard.entryPositions.get("Manipulator")[row][col] == true, i, j); - } - } + // for (int i = 0; i < 8; i++) { + // for (int j = 0; j < 6; j++) { + // final int row = i; + // final int col = j; + // NAR_Shuffleboard.addData("TESTER", "X: " + i + " Y: " + j, ()-> NAR_Shuffleboard.entryPositions.get("Manipulator")[row][col] == true, i, j); + // } + // } } } diff --git a/src/main/java/frc/team3128/subsystems/NAR_PIDSubsystem.java b/src/main/java/frc/team3128/subsystems/NAR_PIDSubsystem.java index 23907ce..181b5f8 100644 --- a/src/main/java/frc/team3128/subsystems/NAR_PIDSubsystem.java +++ b/src/main/java/frc/team3128/subsystems/NAR_PIDSubsystem.java @@ -18,7 +18,7 @@ /** * A subsystem based off of {@link PIDSubsystem} * @since 2023 CHARGED UP - * @author Mason Lam, Arav Chadha, Peter Ma + * @author Mason Lam */ public abstract class NAR_PIDSubsystem extends SubsystemBase { protected final PIDController m_controller; @@ -82,20 +82,9 @@ public void initShuffleboard(double kS, double kV, double kG) { this.kG = NAR_Shuffleboard.debug(getName(), "kG", kG, 3, 2); NAR_Shuffleboard.addData(getName(), "atSetpoint", ()-> atSetpoint(), 0, 2); - NAR_Shuffleboard.addData(getName(), "TestSendable", NAR_Shuffleboard.entryPositions.get(getName())[0][0] == true, 6, 3); // TODO test - pls delete - NAR_Shuffleboard.addData(getName(), "TestData", NAR_Shuffleboard.entryPositions.get(getName())[1][0] == true, 7, 3); // TODO test - pls delete NAR_Shuffleboard.addSendable(getName(), getName(), this, 4, 0); - // Print entryPositions: - // if (getName().equals("Wrist")) { // To ensure this check is done only once - // for (int i = 0; i < 8; i++) { - // for (int j = 0; j < 6; j++) { - // final int row = i; - // final int col = j; - // NAR_Shuffleboard.addData("TESTER", "X: " + i + " Y: " + j, ()-> NAR_Shuffleboard.entryPositions.get("Manipulator")[row][col] == true, i, j); - // } - // } - // } + NAR_Shuffleboard.addData(getName(), "TETS", ()-> getSetpoint()); }