diff --git a/simgui-ds.json b/simgui-ds.json index 179e064..e695a15 100644 --- a/simgui-ds.json +++ b/simgui-ds.json @@ -1,14 +1,13 @@ { - "Keyboard 0 Settings": { + "Joysticks": { "window": { - "visible": true + "visible": false } }, "keyboardJoysticks": [ { "axisConfig": [ { - "decKey": 65, "incKey": 68 }, { @@ -29,10 +28,11 @@ "axisCount": 5, "buttonCount": 4, "buttonKeys": [ - 90, + 65, 88, 67, - 86 + 86, + -1 ], "povConfig": [ { diff --git a/simgui.json b/simgui.json index 18af23d..2257382 100644 --- a/simgui.json +++ b/simgui.json @@ -1,6 +1,16 @@ { "HALProvider": { + "DIO": { + "window": { + "visible": true + } + }, "Other Devices": { + "SPARK MAX [1] RELATIVE ENCODER": { + "header": { + "open": true + } + }, "SPARK MAX [2]": { "header": { "open": true @@ -21,6 +31,16 @@ "open": true } }, + "Talon FX (v6)[10]": { + "header": { + "open": true + } + }, + "Talon FX (v6)[12]": { + "header": { + "open": true + } + }, "Talon FX (v6)[2]/Rotor Sensor": { "header": { "open": true @@ -51,15 +71,43 @@ "open": true } } + }, + "RoboRIO": { + "6V Rail": { + "open": true + }, + "RoboRIO Input": { + "open": true + } } }, "NTProvider": { "types": { "/FMSInfo": "FMSInfo", "/LiveWindow/SwerveSubsystem": "Subsystem", + "/LiveWindow/Ungrouped/DigitalInput[0]": "Digital Input", + "/LiveWindow/Ungrouped/DigitalInput[3]": "Digital Input", + "/LiveWindow/Ungrouped/PIDController[12]": "PIDController", + "/LiveWindow/Ungrouped/PIDController[13]": "PIDController", "/LiveWindow/Ungrouped/PIDController[1]": "PIDController", + "/LiveWindow/Ungrouped/PIDController[2]": "PIDController", + "/LiveWindow/Ungrouped/PIDController[3]": "PIDController", + "/LiveWindow/Ungrouped/PIDController[4]": "PIDController", + "/LiveWindow/Ungrouped/PIDController[5]": "PIDController", + "/LiveWindow/Ungrouped/PIDController[6]": "PIDController", + "/LiveWindow/Ungrouped/PIDController[7]": "PIDController", + "/LiveWindow/Ungrouped/PIDController[8]": "PIDController", "/LiveWindow/Ungrouped/Pigeon 2 [13]": "Gyro", "/LiveWindow/Ungrouped/Scheduler": "Scheduler", + "/LiveWindow/Ungrouped/Talon FX (v6) [10]": "Motor Controller", + "/LiveWindow/Ungrouped/Talon FX (v6) [11]": "Motor Controller", + "/LiveWindow/Ungrouped/Talon SRX [13]": "Motor Controller", + "/LiveWindow/Ungrouped/Victor SPX [14]": "Motor Controller", + "/Shuffleboard/Autonomous/Choose Autonomous Routine": "String Chooser", + "/Shuffleboard/Joint Subsystem/Closed Loop Command": "Command", + "/Shuffleboard/Joint Subsystem/Update Controllers Parameters Command": "Command", + "/SmartDashboard/ADXRS450_Gyro[0]": "Gyro", + "/SmartDashboard/Alerts": "Alerts", "/SmartDashboard/Encoders": "Alerts", "/SmartDashboard/Field": "Field2d", "/SmartDashboard/IMU": "Alerts", @@ -118,22 +166,51 @@ } }, "NetworkTables": { + "retained": { + "Shuffleboard": { + "Main": { + "open": true + }, + "open": true + } + }, "transitory": { "FMSInfo": { "open": true }, "SmartDashboard": { - "Field": { + "Joint Subsystem": { + "Absolute Encoder": { + "open": true + }, "open": true }, - "open": true, - "swerve": { - "open": true - } + "open": true } } }, "NetworkTables Info": { + "Clients": { + "open": true + }, + "Connections": { + "open": true + }, + "Server": { + "Subscribers": { + "open": true + }, + "open": true + }, + "shuffleboard@1": { + "Publishers": { + "open": true + }, + "Subscribers": { + "open": true + }, + "open": true + }, "visible": true } } diff --git a/src/main/deploy/swerve/modules/backleft.json b/src/main/deploy/swerve/modules/backleft.json index 66bf66f..f916d49 100644 --- a/src/main/deploy/swerve/modules/backleft.json +++ b/src/main/deploy/swerve/modules/backleft.json @@ -1,12 +1,12 @@ { "location": { - "front": -10.531, - "left": 10.531 + "front": 10.531, + "left": -10.531 }, - "absoluteEncoderOffset": 82, + "absoluteEncoderOffset": -214, "drive": { "type": "sparkmax_neo", - "id": 7, + "id": 3, "canbus": null }, "inverted": { @@ -15,12 +15,12 @@ }, "angle": { "type": "sparkmax_neo", - "id": 9, + "id": 2, "canbus": null }, "encoder": { "type": "ma3", - "id": 3, + "id": 0, "canbus": null }, "absoluteEncoderInverted": true diff --git a/src/main/deploy/swerve/modules/backright.json b/src/main/deploy/swerve/modules/backright.json index f2af4ba..1f296ca 100644 --- a/src/main/deploy/swerve/modules/backright.json +++ b/src/main/deploy/swerve/modules/backright.json @@ -1,26 +1,26 @@ { "location": { - "front": -10.531, - "left": -10.531 + "front": 10.531, + "left": 10.531 }, - "absoluteEncoderOffset": 148.7, + "absoluteEncoderOffset": -289, "drive": { "type": "sparkmax_neo", - "id": 5, + "id": 1, "canbus": null }, "inverted": { - "drive": false, + "drive": true, "angle": false }, "angle": { "type": "sparkmax_neo", - "id": 6, + "id": 4, "canbus": null }, "encoder": { "type": "ma3", - "id": 2, + "id": 1, "canbus": null }, "absoluteEncoderInverted": true diff --git a/src/main/deploy/swerve/modules/frontleft.json b/src/main/deploy/swerve/modules/frontleft.json index 63c41d4..179a57c 100644 --- a/src/main/deploy/swerve/modules/frontleft.json +++ b/src/main/deploy/swerve/modules/frontleft.json @@ -1,26 +1,26 @@ { "location": { - "front": 10.531, - "left": 10.531 + "front": -10.531, + "left": -10.531 }, - "absoluteEncoderOffset": 251.0, + "absoluteEncoderOffset": -91, "drive": { "type": "sparkmax_neo", - "id": 1, + "id": 5, "canbus": null }, "inverted": { - "drive": false, + "drive": true, "angle": false }, "angle": { "type": "sparkmax_neo", - "id": 4, + "id": 6, "canbus": null }, "encoder": { "type": "ma3", - "id": 1, + "id": 2, "canbus": null }, "absoluteEncoderInverted": true diff --git a/src/main/deploy/swerve/modules/frontright.json b/src/main/deploy/swerve/modules/frontright.json index e84afa5..38aa2f0 100644 --- a/src/main/deploy/swerve/modules/frontright.json +++ b/src/main/deploy/swerve/modules/frontright.json @@ -1,26 +1,26 @@ { "location": { - "front": 10.531, - "left": -10.531 + "front": -10.531, + "left": 10.531 }, - "absoluteEncoderOffset": 329.1, + "absoluteEncoderOffset": -270, "drive": { "type": "sparkmax_neo", - "id": 3, + "id": 7, "canbus": null }, "inverted": { - "drive": false, + "drive": true, "angle": false }, "angle": { "type": "sparkmax_neo", - "id": 2, + "id": 9, "canbus": null }, "encoder": { "type": "ma3", - "id": 0, + "id": 3, "canbus": null }, "absoluteEncoderInverted": true diff --git a/src/main/deploy/swerve/modules/pidfproperties.json b/src/main/deploy/swerve/modules/pidfproperties.json index 9b20fa1..25bf468 100644 --- a/src/main/deploy/swerve/modules/pidfproperties.json +++ b/src/main/deploy/swerve/modules/pidfproperties.json @@ -7,7 +7,7 @@ "iz": 0 }, "angle": { - "p": 0.015, + "p": 0.025, "i": 0, "d": 0.2, "f": 0, diff --git a/src/main/deploy/swerve/swervedrive.json b/src/main/deploy/swerve/swervedrive.json index e3f1854..9ea97af 100644 --- a/src/main/deploy/swerve/swervedrive.json +++ b/src/main/deploy/swerve/swervedrive.json @@ -1,7 +1,7 @@ { "imu": { - "type": "navx_usb", - "id": 0, + "type": "pigeon", + "id": 19, "canbus": null }, "invertedIMU": false, diff --git a/src/main/java/frc/robot/Constants.java b/src/main/java/frc/robot/Constants.java index b5b7e09..2d6db25 100644 --- a/src/main/java/frc/robot/Constants.java +++ b/src/main/java/frc/robot/Constants.java @@ -8,44 +8,53 @@ import edu.wpi.first.math.util.Units; import swervelib.math.Matter; -/** - * The Constants class provides a convenient place for teams to hold robot-wide numerical or boolean constants. This - * class should not be used for any other purpose. All constants should be declared globally (i.e. public static). Do - * not put anything functional in this class. - * - *

It is advised to statically import this class (or one of its inner classes) wherever the - * constants are needed, to reduce verbosity. - */ -public final class Constants -{ - - public static final double ROBOT_MASS = (148 - 20.3) * 0.453592; // 32lbs * kg per pound - public static final Matter CHASSIS = new Matter(new Translation3d(0, 0, Units.inchesToMeters(8)), ROBOT_MASS); - public static final double LOOP_TIME = 0.13; //s, 20ms + 110ms sprk max velocity lag - public static final double MAX_SPEED = Units.feetToMeters(14.5); - // Maximum speed of the robot in meters per second, used to limit acceleration. - -// public static final class AutonConstants -// { -// -// public static final PIDConstants TRANSLATION_PID = new PIDConstants(0.7, 0, 0); -// public static final PIDConstants ANGLE_PID = new PIDConstants(0.4, 0, 0.01); -// } - - public static final class DrivebaseConstants - { - - // Hold time on motor brakes when disabled +public final class Constants { + public static final double ROBOT_MASS = (148 - 20.3) * 0.453592; + public static final Matter CHASSIS = new Matter(new Translation3d(0, 0, Units.inchesToMeters(8)), ROBOT_MASS); + public static final double LOOP_TIME = 0.13; + public static final double MAX_SPEED = Units.feetToMeters(14.5); + public static final boolean DEV_MODE = false; + + public static class HIDConstants { + public static final double DEADBAND = 0.1; + public static final double LEFT_Y_DEADBAND = 0.1; + public static final double RIGHT_X_DEADBAND = 0.1; + public static final double TURN_CONSTANT = 6; + } + + public static final class SwerveConstants { public static final double WHEEL_LOCK_TIME = 10; // seconds } - public static class OperatorConstants - { + public static class IntakeConstants { + public static final int MOTOR_CAN_ID = 12; + public static final double INTAKE = -0.4; + public static final double OUTTAKE = 1.0; + } - // Joystick Deadband - public static final double DEADBAND = 0.1; - public static final double LEFT_Y_DEADBAND = 0.1; - public static final double RIGHT_X_DEADBAND = 0.1; - public static final double TURN_CONSTANT = 6; + public static class JointConstants { + public static final int LEFT_MOTOR_CAN_ID = 13; + public static final int RIGHT_MOTOR_CAN_ID = 14; + public static final int RIGHT_ENCODER_DIO_PORT = 3; + public static final double ASCEND = -0.85; + public static final double DESCEND = 0.7; + } + + public static class PuncherConstants { + public static final int LEFT_MOTOR_CAN_ID = 10; + public static final int RIGHT_MOTOR_CAN_ID = 11; + public static final int RELEASE_MOTOR_CAN_ID = 16; + public static final int ENCODER_DIO_PORT_A = 4; + public static final int ENCODER_DIO_PORT_B = 5; + public static final double POSITION = 100; + public static final double RELEASE = 0.3; + public static final double TIGHTEN = 0.31; + } + + public static class ElevatorConstants { + public static final int MOTOR_CAN_ID = 15; + public static final int LIMIT_SWITCH_DIO_PORT = 0; + public static final double ASCEND = 1; + public static final double DESCEND = -1; } -} +} \ No newline at end of file diff --git a/src/main/java/frc/robot/Robot.java b/src/main/java/frc/robot/Robot.java index b301879..cb768b7 100644 --- a/src/main/java/frc/robot/Robot.java +++ b/src/main/java/frc/robot/Robot.java @@ -10,166 +10,98 @@ import edu.wpi.first.wpilibj2.command.Command; import edu.wpi.first.wpilibj2.command.CommandScheduler; -/** - * The VM is configured to automatically run this class, and to call the functions corresponding to each mode, as - * described in the TimedRobot documentation. If you change the name of this class or the package after creating this - * project, you must also update the build.gradle file in the project. - */ -public class Robot extends TimedRobot -{ - - private static Robot instance; - private Command m_autonomousCommand; +public class Robot extends TimedRobot { + private static Robot instance; + private Command m_autonomousCommand; private RobotContainer m_robotContainer; private Timer disabledTimer; - public Robot() - { + public Robot() { instance = this; + enableLiveWindowInTest(true); } - public static Robot getInstance() - { + public static Robot getInstance() { return instance; } - /** - * This function is run when the robot is first started up and should be used for any initialization code. - */ @Override - public void robotInit() - { - // Instantiate our RobotContainer. This will perform all our button bindings, and put our - // autonomous chooser on the dashboard. + public void robotInit() { m_robotContainer = new RobotContainer(); - - // Create a timer to disable motor brake a few seconds after disable. This will let the robot stop - // immediately when disabled, but then also let it be pushed more disabledTimer = new Timer(); - if (isSimulation()) - { + if (isSimulation()) { DriverStation.silenceJoystickConnectionWarning(true); } } - /** - * This function is called every 20 ms, no matter the mode. Use this for items like diagnostics that you want ran - * during disabled, autonomous, teleoperated and test. - * - *

This runs after the mode specific periodic functions, but before LiveWindow and - * SmartDashboard integrated updating. - */ @Override - public void robotPeriodic() - { - // Runs the Scheduler. This is responsible for polling buttons, adding newly-scheduled - // commands, running already-scheduled commands, removing finished or interrupted commands, - // and running subsystem periodic() methods. This must be called from the robot's periodic - // block in order for anything in the Command-based framework to work. + public void robotPeriodic() { CommandScheduler.getInstance().run(); } - /** - * This function is called once each time the robot enters Disabled mode. - */ @Override - public void disabledInit() - { + public void disabledInit() { + m_robotContainer.resetPuncherSubsystemEncoders(); m_robotContainer.setMotorBrake(true); disabledTimer.reset(); disabledTimer.start(); } @Override - public void disabledPeriodic() - { - if (disabledTimer.hasElapsed(Constants.DrivebaseConstants.WHEEL_LOCK_TIME)) - { + public void disabledPeriodic() { + if (disabledTimer.hasElapsed(Constants.SwerveConstants.WHEEL_LOCK_TIME)) { m_robotContainer.setMotorBrake(false); disabledTimer.stop(); disabledTimer.reset(); } } - /** - * This autonomous runs the autonomous command selected by your {@link RobotContainer} class. - */ @Override - public void autonomousInit() - { + public void autonomousInit() { m_robotContainer.setMotorBrake(true); m_autonomousCommand = m_robotContainer.getAutonomousCommand(); - // schedule the autonomous command (example) - if (m_autonomousCommand != null) - { + if (m_autonomousCommand != null) { m_autonomousCommand.schedule(); } } - /** - * This function is called periodically during autonomous. - */ @Override - public void autonomousPeriodic() - { + public void autonomousPeriodic() { } @Override - public void teleopInit() - { - // This makes sure that the autonomous stops running when - // teleop starts running. If you want the autonomous to - // continue until interrupted by another command, remove - // this line or comment it out. - if (m_autonomousCommand != null) - { + public void teleopInit() { + m_robotContainer.resetPuncherSubsystemEncoders(); + m_robotContainer.zeroGyro(); + if (m_autonomousCommand != null) { m_autonomousCommand.cancel(); - } else - { + } else { CommandScheduler.getInstance().cancelAll(); } } - /** - * This function is called periodically during operator control. - */ @Override - public void teleopPeriodic() - { + public void teleopPeriodic() { } @Override - public void testInit() - { - // Cancels all running commands at the start of test mode. + public void testInit() { CommandScheduler.getInstance().cancelAll(); } - /** - * This function is called periodically during test mode. - */ @Override - public void testPeriodic() - { + public void testPeriodic() { } - /** - * This function is called once when the robot is first started up. - */ @Override - public void simulationInit() - { + public void simulationInit() { } - /** - * This function is called periodically whilst in simulation. - */ @Override - public void simulationPeriodic() - { + public void simulationPeriodic() { } } diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index 18f7d10..845dec9 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -5,180 +5,99 @@ package frc.robot; import com.pathplanner.lib.auto.NamedCommands; -import edu.wpi.first.math.geometry.Pose2d; -import edu.wpi.first.math.geometry.Rotation2d; -import edu.wpi.first.math.geometry.Translation2d; import edu.wpi.first.wpilibj.DriverStation; import edu.wpi.first.wpilibj.Filesystem; -import edu.wpi.first.wpilibj.RobotBase; +import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; +import edu.wpi.first.wpilibj.smartdashboard.SendableChooser; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; import edu.wpi.first.wpilibj2.command.Command; import edu.wpi.first.wpilibj2.command.Commands; +import edu.wpi.first.wpilibj2.command.PrintCommand; +import edu.wpi.first.wpilibj2.command.StartEndCommand; import edu.wpi.first.wpilibj2.command.button.CommandXboxController; -import edu.wpi.first.wpilibj2.command.button.Trigger; -import frc.robot.Constants.OperatorConstants; -import frc.robot.subsystems.Shooter; +import frc.robot.buttonBindings.DriverButtonBindings; +import frc.robot.buttonBindings.DriverTankButtonBindings; +import frc.robot.buttonBindings.OperatorButtonBindings; +import frc.robot.subsystems.ElevatorSubsystem; +import frc.robot.subsystems.IntakeSubsystem; +import frc.robot.subsystems.JointSubsystem; +import frc.robot.subsystems.PuncherSubsystem; import frc.robot.subsystems.swervedrive.SwerveSubsystem; +import frc.robot.subsystems.swervetank.Drivetrain; + import java.io.File; -import swervelib.SwerveInputStream; - -/** - * This class is where the bulk of the robot should be declared. Since - * Command-based is a "declarative" paradigm, very - * little robot logic should actually be handled in the {@link Robot} periodic - * methods (other than the scheduler calls). - * Instead, the structure of the robot (including subsystems, commands, and - * trigger mappings) should be declared here. - */ + public class RobotContainer { + private final CommandXboxController driverXbox; + private final CommandXboxController operatorXbox; + + private final SwerveSubsystem swerveSubsystem; + //private final Drivetrain swerveSubsystem; + + private final IntakeSubsystem intakeSubsystem; + private final PuncherSubsystem puncherSubsystem; + private final JointSubsystem jointSubsystem; + private final ElevatorSubsystem elevatorSubsystem; + + private final DriverButtonBindings driverButtonBindings; + //private final DriverTankButtonBindings driverButtonBindings; + + private final OperatorButtonBindings operatorButtonBindings; + SendableChooser autonomousChooser; - // Replace with CommandPS4Controller or CommandJoystick if needed - final CommandXboxController driverXbox = new CommandXboxController(0); - // The robot's subsystems and commands are defined here... - private final SwerveSubsystem drivebase = new SwerveSubsystem(new File(Filesystem.getDeployDirectory(), - "swerve")); - private Shooter shooter; - /** - * Converts driver input into a field-relative ChassisSpeeds that is controlled - * by angular velocity. - */ - SwerveInputStream driveAngularVelocity = SwerveInputStream.of(drivebase.getSwerveDrive(), - () -> driverXbox.getLeftY() * -1, - () -> driverXbox.getLeftX() * -1) - // Modificando para usar os triggers para controlar a rotação - .withControllerRotationAxis(() -> { - double leftTrigger = driverXbox.getLeftTriggerAxis(); // Valor entre 0 e 1 - double rightTrigger = driverXbox.getRightTriggerAxis(); // Valor entre 0 e 1 - - // Definindo a rotação com base nos triggers - double rotation = rightTrigger - leftTrigger; - - return rotation; // Retorna o valor da rotação - }) - .deadband(OperatorConstants.DEADBAND) - .scaleTranslation(0.8) - .allianceRelativeControl(true); - - /** - * Clone's the angular velocity input stream and converts it to a fieldRelative - * input stream. - */ - SwerveInputStream driveDirectAngle = driveAngularVelocity.copy().withControllerHeadingAxis(driverXbox::getRightX, - driverXbox::getRightY) - .headingWhile(true); - - /** - * Clone's the angular velocity input stream and converts it to a robotRelative - * input stream. - */ - SwerveInputStream driveRobotOriented = driveAngularVelocity.copy().robotRelative(true) - .allianceRelativeControl(false); - - SwerveInputStream driveAngularVelocityKeyboard = SwerveInputStream.of(drivebase.getSwerveDrive(), - () -> -driverXbox.getLeftY(), - () -> -driverXbox.getLeftX()) - .withControllerRotationAxis(() -> driverXbox.getRawAxis( - 2)) - .deadband(OperatorConstants.DEADBAND) - .scaleTranslation(0.8) - .allianceRelativeControl(true); - // Derive the heading axis with math! - SwerveInputStream driveDirectAngleKeyboard = driveAngularVelocityKeyboard.copy() - .withControllerHeadingAxis(() -> Math.sin( - driverXbox.getRawAxis( - 2) * - Math.PI) - * - (Math.PI * - 2), - () -> Math.cos( - driverXbox.getRawAxis( - 2) * - Math.PI) - * - (Math.PI * - 2)) - .headingWhile(true); - - /** - * The container for the robot. Contains subsystems, OI devices, and commands. - */ public RobotContainer() { - //shooter = new Shooter(drivebase.getVision()); + driverXbox = new CommandXboxController(0); + operatorXbox = new CommandXboxController(1); + + swerveSubsystem = new SwerveSubsystem(new File(Filesystem.getDeployDirectory(),"swerve")); + //swerveSubsystem = new Drivetrain(); + intakeSubsystem = new IntakeSubsystem(); + puncherSubsystem = new PuncherSubsystem(); + jointSubsystem = new JointSubsystem(); + elevatorSubsystem = new ElevatorSubsystem(); + + driverButtonBindings = new DriverButtonBindings(driverXbox, swerveSubsystem, intakeSubsystem, jointSubsystem, puncherSubsystem, elevatorSubsystem); + //driverButtonBindings = new DriverTankButtonBindings(driverXbox, swerveSubsystem, elevatorSubsystem); + + operatorButtonBindings = new OperatorButtonBindings(operatorXbox); configureBindings(); + + autonomousChooser = new SendableChooser (); + autonomousChooserSetup(); + DriverStation.silenceJoystickConnectionWarning(true); - NamedCommands.registerCommand("test", Commands.print("I EXIST")); } - /** - * Use this method to define your trigger->command mappings. Triggers can be - * created via the - * {@link Trigger#Trigger(java.util.function.BooleanSupplier)} constructor with - * an arbitrary predicate, or via the - * named factories in - * {@link edu.wpi.first.wpilibj2.command.button.CommandGenericHID}'s subclasses - * for - * {@link CommandXboxController - * Xbox}/{@link edu.wpi.first.wpilibj2.command.button.CommandPS4Controller PS4} - * controllers or {@link edu.wpi.first.wpilibj2.command.button.CommandJoystick - * Flight joysticks}. - */ private void configureBindings() { - - Command driveFieldOrientedDirectAngle = drivebase.driveFieldOriented(driveDirectAngle); - Command driveFieldOrientedAnglularVelocity = drivebase.driveFieldOriented(driveAngularVelocity); - Command driveRobotOrientedAngularVelocity = drivebase.driveFieldOriented(driveRobotOriented); - Command driveSetpointGen = drivebase.driveWithSetpointGeneratorFieldRelative( - driveDirectAngle); - Command driveFieldOrientedDirectAngleKeyboard = drivebase.driveFieldOriented(driveDirectAngleKeyboard); - Command driveFieldOrientedAnglularVelocityKeyboard = drivebase.driveFieldOriented(driveAngularVelocityKeyboard); - Command driveSetpointGenKeyboard = drivebase.driveWithSetpointGeneratorFieldRelative( - driveDirectAngleKeyboard); - - if (RobotBase.isSimulation()) { - drivebase.setDefaultCommand(driveFieldOrientedDirectAngleKeyboard); - } else { - drivebase.setDefaultCommand(driveFieldOrientedAnglularVelocity); - } - - if (Robot.isSimulation()) { - driverXbox.start().onTrue(Commands.runOnce(() -> drivebase.resetOdometry(new Pose2d(3, 3, new Rotation2d())))); - driverXbox.button(1).whileTrue(drivebase.sysIdDriveMotorCommand()); - - } - if (DriverStation.isTest()) { - drivebase.setDefaultCommand(driveFieldOrientedAnglularVelocity); // Overrides drive command above! - - driverXbox.x().whileTrue(Commands.runOnce(drivebase::lock, drivebase).repeatedly()); - driverXbox.y().whileTrue(drivebase.driveToDistanceCommand(1.0, 0.2)); - driverXbox.start().onTrue((Commands.runOnce(drivebase::zeroGyro))); - driverXbox.back().whileTrue(drivebase.centerModulesCommand()); - driverXbox.leftBumper().onTrue(Commands.none()); - driverXbox.rightBumper().onTrue(Commands.none()); - } else { - driverXbox.a().onTrue((Commands.runOnce(drivebase::zeroGyro))); - driverXbox.x().onTrue(Commands.runOnce(drivebase::addFakeVisionReading)); - driverXbox.b().whileTrue( - drivebase.driveToPose( - new Pose2d(new Translation2d(4, 4), Rotation2d.fromDegrees(0)))); - driverXbox.start().whileTrue(Commands.none()); - driverXbox.back().whileTrue(Commands.none()); - driverXbox.leftBumper().whileTrue(Commands.runOnce(drivebase::lock, drivebase).repeatedly()); - driverXbox.rightBumper().onTrue(Commands.none()); - } - + driverButtonBindings.configureBindings(); + operatorButtonBindings.configureBindings(); } - /** - * Use this to pass the autonomous command to the main {@link Robot} class. - * - * @return the command to run in autonomous - */ public Command getAutonomousCommand() { - // An example command will be run in autonomous - return drivebase.getAutonomousCommand("testauto"); + return null; + //return swerveSubsystem.autonomousCommand(); + //return null; //autonomousChooser.getSelected(); + } + + public void autonomousChooserSetup() { + Shuffleboard.getTab("Autonomous").add("Choose Autonomous Routine", autonomousChooser); + + autonomousChooser.setDefaultOption("No auto", new PrintCommand("No Auto Selected")); + autonomousChooser.addOption("Also no auto", new PrintCommand("Also No Auto Selected")); + + NamedCommands.registerCommand("test", Commands.print("I EXIST")); } public void setMotorBrake(boolean brake) { - drivebase.setMotorBrake(brake); + swerveSubsystem.setMotorBrake(brake); + } + + public void resetPuncherSubsystemEncoders() { + //puncherSubsystem.resetEncoders(); + //puncherSubsystem.resetState(); + } + + public void zeroGyro() { + swerveSubsystem.zeroGyro(); } } diff --git a/src/main/java/frc/robot/Utils.java b/src/main/java/frc/robot/Utils.java deleted file mode 100644 index e077134..0000000 --- a/src/main/java/frc/robot/Utils.java +++ /dev/null @@ -1,5 +0,0 @@ -package frc.robot; - -public class Utils { - -} diff --git a/src/main/java/frc/robot/buttonBindings/DriverButtonBindings.java b/src/main/java/frc/robot/buttonBindings/DriverButtonBindings.java new file mode 100644 index 0000000..6c43e1c --- /dev/null +++ b/src/main/java/frc/robot/buttonBindings/DriverButtonBindings.java @@ -0,0 +1,249 @@ +package frc.robot.buttonBindings; + +import edu.wpi.first.math.geometry.Pose2d; +import edu.wpi.first.math.geometry.Rotation2d; +import edu.wpi.first.wpilibj.DriverStation; +import edu.wpi.first.wpilibj.RobotBase; +import edu.wpi.first.wpilibj.RobotState; +import edu.wpi.first.wpilibj.GenericHID.RumbleType; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.Commands; +import edu.wpi.first.wpilibj2.command.ConditionalCommand; +import edu.wpi.first.wpilibj2.command.button.CommandXboxController; +import frc.robot.Constants; +import frc.robot.Constants.HIDConstants; +import frc.robot.Robot; + +import frc.robot.subsystems.ElevatorSubsystem; +import frc.robot.subsystems.IntakeSubsystem; +import frc.robot.subsystems.JointSubsystem; +import frc.robot.subsystems.PuncherSubsystem; +import frc.robot.subsystems.swervedrive.SwerveSubsystem; +import swervelib.SwerveInputStream; + +public class DriverButtonBindings { + private final CommandXboxController driverXbox; + + private final SwerveSubsystem swerveSubsystem; + private final IntakeSubsystem intakeSubsystem; + private final JointSubsystem jointSubsystem; + private final PuncherSubsystem puncherSubsystem; + private final ElevatorSubsystem elevatorSubsystem; + + private final SwerveInputStream driveDirectAngleSwerveInputStream; + private final SwerveInputStream driveRobotOrientedSwerveInputStream; + private final SwerveInputStream driveAngularVelocityKeyboardSwerveInputStream; + private final SwerveInputStream driveDirectAngleKeyboardSwerveInputStream; + private final SwerveInputStream driveAngularVelocitySwerveInputStream; + + private final Command driveFieldOrientedDirectAngleCommand; + private final Command driveFieldOrientedAngularVelocityCommand; + private final Command driveRobotOrientedAngularVelocityCommand; + private final Command driveSetpointGenCommand; + private final Command driveFieldOrientedDirectAngleKeyboardCommand; + private final Command driveFieldOrientedAngularVelocityKeyboardCommand; + private final Command driveSetpointGenKeyboardCommand; + + private final Command swerveZeroGyroCommand; + private final Command swerveLockPoseCommand; + private final Command swerveAddFakeVisionReadingCommand; + private final Command swerveCenterModulesCommand; + + private final Command intakeCommand; + private final Command outtakeCommand; + private final Command intakeStopCommand; + private final Command jointAscendCommand; + private final Command jointDescendCommand; + private final Command puncherBuildUpCommand; + private final Command puncherReleaseCommand; + private final Command elevatorAscendCommand; + private final Command elevatorDescendCommand; + private final Command driverFeedbackCommand; + + //private final ConditionalCommand puncherConditionalCommand; + + private final Command testPuncherBuildUpCommand; + private final Command testPuncherReleaseCommand; + private final Command testPuncherPrintCommand; + private final Command testIntakeCommand; + private final Command testOuttakeCommand; + private final Command testElevatorAscendCommand; + private final Command testElevatorDescendCommand; + private final Command testJointCommand; + + + public DriverButtonBindings(CommandXboxController driverXbox, SwerveSubsystem swerveSubsystem, + IntakeSubsystem intakeSubsystem, JointSubsystem jointSubsystem, PuncherSubsystem puncherSubsystem, ElevatorSubsystem elevatorSubsystem) { + this.driverXbox = driverXbox; + + this.swerveSubsystem = swerveSubsystem; + this.intakeSubsystem = intakeSubsystem; + this.jointSubsystem = jointSubsystem; + this.puncherSubsystem = puncherSubsystem; + this.elevatorSubsystem = elevatorSubsystem; + + driveAngularVelocitySwerveInputStream = SwerveInputStream.of(this.swerveSubsystem.getSwerveDrive(), + () -> this.driverXbox.getLeftY() * 1, + () -> this.driverXbox.getLeftX() * 1) + .withControllerRotationAxis(() -> { + double leftTrigger = this.driverXbox.getLeftTriggerAxis(); + double rightTrigger = this.driverXbox.getRightTriggerAxis(); + double rotation = rightTrigger - leftTrigger; + return rotation; + }) + .deadband(HIDConstants.DEADBAND) + .scaleTranslation(0.8) + .allianceRelativeControl(true); + + driveDirectAngleSwerveInputStream = driveAngularVelocitySwerveInputStream.copy().withControllerHeadingAxis + (this.driverXbox::getRightX, this.driverXbox::getRightY).headingWhile(true); + + driveRobotOrientedSwerveInputStream = driveAngularVelocitySwerveInputStream.copy().robotRelative(true) + .allianceRelativeControl(false); + + driveAngularVelocityKeyboardSwerveInputStream = SwerveInputStream.of(this.swerveSubsystem.getSwerveDrive(), + () -> -this.driverXbox.getLeftY(), + () -> -this.driverXbox.getLeftX()) + .withControllerRotationAxis(() -> this.driverXbox.getRawAxis( + 2)) + .deadband(HIDConstants.DEADBAND) + .scaleTranslation(0.8) + .allianceRelativeControl(true); + + driveDirectAngleKeyboardSwerveInputStream = driveAngularVelocityKeyboardSwerveInputStream.copy() + .withControllerHeadingAxis(() -> Math.sin( + this.driverXbox.getRawAxis(2) * Math.PI) * (Math.PI * 2), + () -> Math.cos(this.driverXbox.getRawAxis(2) * Math.PI) * (Math.PI * 2)) + .headingWhile(true); + + driveFieldOrientedDirectAngleCommand = this.swerveSubsystem.driveFieldOriented(driveDirectAngleSwerveInputStream); + driveFieldOrientedAngularVelocityCommand = this.swerveSubsystem.driveFieldOriented(driveAngularVelocitySwerveInputStream); + driveRobotOrientedAngularVelocityCommand = this.swerveSubsystem.driveFieldOriented(driveRobotOrientedSwerveInputStream); + driveSetpointGenCommand = this.swerveSubsystem.driveWithSetpointGeneratorFieldRelative(driveDirectAngleSwerveInputStream); + driveFieldOrientedDirectAngleKeyboardCommand = this.swerveSubsystem.driveFieldOriented(driveDirectAngleKeyboardSwerveInputStream); + driveFieldOrientedAngularVelocityKeyboardCommand = this.swerveSubsystem.driveFieldOriented(driveAngularVelocityKeyboardSwerveInputStream); + driveSetpointGenKeyboardCommand = this.swerveSubsystem.driveWithSetpointGeneratorFieldRelative(driveDirectAngleKeyboardSwerveInputStream); + + swerveZeroGyroCommand = Commands.runOnce(this.swerveSubsystem::zeroGyro); + swerveLockPoseCommand = Commands.runOnce(this.swerveSubsystem::lock, this.swerveSubsystem).repeatedly(); + swerveAddFakeVisionReadingCommand = Commands.runOnce(this.swerveSubsystem::addFakeVisionReading); + swerveCenterModulesCommand = this.swerveSubsystem.centerModulesCommand(); + + intakeCommand = this.intakeSubsystem.percentOutCommand(() -> Constants.IntakeConstants.INTAKE); + outtakeCommand = this.intakeSubsystem.percentOutCommand(() -> Constants.IntakeConstants.OUTTAKE); + intakeStopCommand = this.intakeSubsystem.percentOutCommand(() -> 0); + jointAscendCommand = this.jointSubsystem.percentOutCommand(() -> Constants.JointConstants.ASCEND); + jointDescendCommand = this.jointSubsystem.percentOutCommand(() -> Constants.JointConstants.DESCEND); + puncherBuildUpCommand = this.puncherSubsystem.buildUpCommand(() -> Constants.PuncherConstants.POSITION); + puncherReleaseCommand = this.puncherSubsystem.releaseCommand(() -> Constants.PuncherConstants.RELEASE, () -> Constants.PuncherConstants.TIGHTEN); + elevatorAscendCommand = this.elevatorSubsystem.percentOutCommand(() -> Constants.ElevatorConstants.ASCEND); + elevatorDescendCommand = this.elevatorSubsystem.descendCommand(); + + driverFeedbackCommand = Commands.startEnd(() -> this.driverXbox.setRumble(RumbleType.kBothRumble, 1), () -> this.driverXbox.setRumble(RumbleType.kBothRumble, 0), puncherSubsystem).withTimeout(2); + //puncherConditionalCommand = new ConditionalCommand(puncherBuildUpCommand, driverFeedbackCommand, () -> jointSubsystem.isSafeBuildUpAngle() && !puncherSubsystem.isPuncherReady()); + + testPuncherBuildUpCommand = this.puncherSubsystem.testBuildUpCommand(); + testPuncherReleaseCommand = this.puncherSubsystem.testReleaseCommand(); + testPuncherPrintCommand = this.puncherSubsystem.testPrintCommand(); + testIntakeCommand = this.intakeSubsystem.testIntakeCommand(); + testOuttakeCommand = this.intakeSubsystem.testOuttakeCommand(); + testElevatorAscendCommand = this.elevatorSubsystem.testAscendCommand(); + testElevatorDescendCommand = this.elevatorSubsystem.testDescendCommand(); + testJointCommand = this.jointSubsystem.testOpenLoopCommand(); + } + + public void configureBindings() { + drivebaseDefaultButtonBindings(); + drivebaseSimulationButtonBindings(); + drivebaseTestButtonBindings(); + + if(Constants.DEV_MODE) { + intakeTestButtonBindings(); + jointTestButtonBindings(); + puncherTestButtonBindings(); + elevatorTestButtonBindings(); + } else { + intakeButtonBindings(); + jointButtonBindings(); + puncherButtonBindings(); + elevatorButtonBindings(); + } + } + + public void drivebaseDefaultButtonBindings() { + if (!RobotBase.isSimulation()) { + swerveSubsystem.setDefaultCommand(driveRobotOrientedAngularVelocityCommand); + } + + if (!DriverStation.isTest()) { + driverXbox.start().onTrue(swerveZeroGyroCommand); + driverXbox.leftStick().whileTrue(swerveLockPoseCommand); + } + } + + public void drivebaseSimulationButtonBindings() { + if (RobotBase.isSimulation()) { + swerveSubsystem.setDefaultCommand(driveFieldOrientedDirectAngleKeyboardCommand); + } + + if (Robot.isSimulation()) { + driverXbox.start().onTrue(Commands.runOnce(() -> swerveSubsystem.resetOdometry(new Pose2d(3, 3, new Rotation2d())))); + driverXbox.button(1).whileTrue(swerveSubsystem.sysIdDriveMotorCommand()); + } + } + + public void drivebaseTestButtonBindings() { + if (DriverStation.isTest()) { + swerveSubsystem.setDefaultCommand(driveFieldOrientedAngularVelocityCommand); + driverXbox.x().whileTrue(swerveLockPoseCommand); + driverXbox.start().onTrue(swerveZeroGyroCommand); + driverXbox.back().whileTrue(swerveCenterModulesCommand); + driverXbox.x().onTrue(swerveAddFakeVisionReadingCommand); + } + } + + public void intakeTestButtonBindings() { + driverXbox.y().whileTrue(testIntakeCommand); //TESTAR + driverXbox.x().whileTrue(testOuttakeCommand); //TESTAR + driverXbox.b().whileTrue(intakeStopCommand); //TESTAR + } + + public void jointTestButtonBindings() { + //driverXbox.a().whileTrue(testJointCommand); + driverXbox.povUp().whileTrue(jointAscendCommand); + driverXbox.povDown().whileTrue(jointDescendCommand); + } + + public void puncherTestButtonBindings() { + //driverXbox.leftBumper().onTrue(puncherConditionalCommand); //TESTAR + driverXbox.leftBumper().whileTrue(puncherBuildUpCommand); + driverXbox.rightBumper().onTrue(testPuncherReleaseCommand); + + } + + public void elevatorTestButtonBindings() { + driverXbox.povLeft().whileTrue(testElevatorAscendCommand); + driverXbox.povRight().whileTrue(testElevatorDescendCommand); + } + + public void intakeButtonBindings() { + driverXbox.y().whileTrue(intakeCommand); //TESTAR + driverXbox.x().whileTrue(outtakeCommand); //TESTAR + driverXbox.b().whileTrue(intakeStopCommand); //TESTAR + } + + public void jointButtonBindings() { + driverXbox.povUp().whileTrue(jointAscendCommand); + driverXbox.povDown().whileTrue(jointDescendCommand); + } + + public void puncherButtonBindings() { + driverXbox.leftBumper().whileTrue(puncherBuildUpCommand); + driverXbox.rightBumper().onTrue(testPuncherReleaseCommand); + } + + public void elevatorButtonBindings() { + driverXbox.povLeft().whileTrue(elevatorAscendCommand); + driverXbox.povRight().whileTrue(elevatorDescendCommand); + } +} diff --git a/src/main/java/frc/robot/buttonBindings/DriverTankButtonBindings.java b/src/main/java/frc/robot/buttonBindings/DriverTankButtonBindings.java new file mode 100644 index 0000000..a9d2ecc --- /dev/null +++ b/src/main/java/frc/robot/buttonBindings/DriverTankButtonBindings.java @@ -0,0 +1,171 @@ +package frc.robot.buttonBindings; + +import edu.wpi.first.math.geometry.Pose2d; +import edu.wpi.first.math.geometry.Rotation2d; +import edu.wpi.first.wpilibj.DriverStation; +import edu.wpi.first.wpilibj.RobotBase; +import edu.wpi.first.wpilibj.RobotState; +import edu.wpi.first.wpilibj.GenericHID.RumbleType; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.Commands; +import edu.wpi.first.wpilibj2.command.ConditionalCommand; +import edu.wpi.first.wpilibj2.command.button.CommandXboxController; +import frc.robot.Constants; +import frc.robot.Constants.HIDConstants; +import frc.robot.Robot; + +import frc.robot.subsystems.ElevatorSubsystem; +import frc.robot.subsystems.IntakeSubsystem; +import frc.robot.subsystems.JointSubsystem; +import frc.robot.subsystems.PuncherSubsystem; +import frc.robot.subsystems.swervedrive.SwerveSubsystem; +import frc.robot.subsystems.swervetank.Drivetrain; +import swervelib.SwerveInputStream; + +public class DriverTankButtonBindings { + private final CommandXboxController driverXbox; + + private final Drivetrain drivetrain; + //private final PuncherSubsystem puncherSubsystem; + private final ElevatorSubsystem elevatorSubsystem; + + private final Command driveCommand; + + /* + private final IntakeSubsystem intakeSubsystem; + private final JointSubsystem jointSubsystem; + + private final Command intakeCommand; + private final Command outtakeCommand; + private final Command intakeStopCommand; + private final Command jointAscendCommand; + private final Command jointDescendCommand; + //private final Command puncherBuildUpCommand; + //private final Command puncherReleaseCommand; + private final Command driverFeedbackCommand; + + //private final ConditionalCommand puncherConditionalCommand; + + //private final Command testPuncherBuildUpCommand; + //private final Command testPuncherReleaseCommand; + //private final Command testPuncherPrintCommand; + private final Command testIntakeCommand; + private final Command testOuttakeCommand; + private final Command testElevatorAscendCommand; + private final Command testElevatorDescendCommand; + private final Command testJointCommand; + */ + + private final Command elevatorAscendCommand; + private final Command elevatorDescendCommand; + + + //public DriverTankButtonBindings(CommandXboxController driverXbox, Drivetrain drivetrain, IntakeSubsystem intakeSubsystem, JointSubsystem jointSubsystem, PuncherSubsystem puncherSubsystem, ElevatorSubsystem elevatorSubsystem) { + public DriverTankButtonBindings(CommandXboxController driverXbox, Drivetrain drivetrain, ElevatorSubsystem elevatorSubsystem) { + this.driverXbox = driverXbox; + + this.drivetrain = drivetrain; + /* + this.intakeSubsystem = intakeSubsystem; + this.jointSubsystem = jointSubsystem; + this.puncherSubsystem = puncherSubsystem; + */ + this.elevatorSubsystem = elevatorSubsystem; + + driveCommand = this.drivetrain.drive(this.driverXbox::getLeftY, () -> this.driverXbox.getRightX()); + + /* + intakeCommand = this.intakeSubsystem.percentOutCommand(() -> Constants.IntakeConstants.INTAKE); + outtakeCommand = this.intakeSubsystem.percentOutCommand(() -> Constants.IntakeConstants.OUTTAKE); + intakeStopCommand = this.intakeSubsystem.percentOutCommand(() -> 0); + jointAscendCommand = this.jointSubsystem.percentOutCommand(() -> Constants.JointConstants.ASCEND); + jointDescendCommand = this.jointSubsystem.percentOutCommand(() -> Constants.JointConstants.DESCEND); + //puncherBuildUpCommand = this.puncherSubsystem.buildUpCommand(() -> Constants.PuncherConstants.POSITION); + //puncherReleaseCommand = this.puncherSubsystem.releaseCommand(() -> Constants.PuncherConstants.RELEASE, () -> Constants.PuncherConstants.TIGHTEN); + */ + + elevatorAscendCommand = this.elevatorSubsystem.percentOutCommand(() -> Constants.ElevatorConstants.ASCEND); + elevatorDescendCommand = this.elevatorSubsystem.descendCommand(); + + + + //driverFeedbackCommand = Commands.startEnd(() -> this.driverXbox.setRumble(RumbleType.kBothRumble, 1), () -> this.driverXbox.setRumble(RumbleType.kBothRumble, 0), puncherSubsystem).withTimeout(2); + //puncherConditionalCommand = new ConditionalCommand(puncherBuildUpCommand, driverFeedbackCommand, () -> jointSubsystem.isSafeBuildUpAngle() && !puncherSubsystem.isPuncherReady()); + + //testPuncherBuildUpCommand = this.puncherSubsystem.testBuildUpCommand(); + //testPuncherReleaseCommand = this.puncherSubsystem.testReleaseCommand(); + //testPuncherPrintCommand = this.puncherSubsystem.testPrintCommand(); + /* + testIntakeCommand = this.intakeSubsystem.testIntakeCommand(); + testOuttakeCommand = this.intakeSubsystem.testOuttakeCommand(); + testElevatorAscendCommand = this.elevatorSubsystem.testAscendCommand(); + testElevatorDescendCommand = this.elevatorSubsystem.testDescendCommand(); + testJointCommand = this.jointSubsystem.testOpenLoopCommand(); + */ + } + + public void configureBindings() { + drivebaseButtonBindings(); + + if(Constants.DEV_MODE) { + //intakeTestButtonBindings(); + //jointTestButtonBindings(); + //puncherTestButtonBindings(); + //elevatorTestButtonBindings(); + } else { + //intakeButtonBindings(); + //jointButtonBindings(); + //puncherButtonBindings(); + elevatorButtonBindings(); + } + } + + public void drivebaseButtonBindings() { + drivetrain.setDefaultCommand(driveCommand); + } + + /* + public void intakeTestButtonBindings() { + driverXbox.y().whileTrue(testIntakeCommand); //TESTAR + driverXbox.x().whileTrue(testOuttakeCommand); //TESTAR + driverXbox.b().whileTrue(intakeStopCommand); //TESTAR + } + + public void jointTestButtonBindings() { + //driverXbox.a().whileTrue(testJointCommand); + driverXbox.povUp().whileTrue(jointAscendCommand); + driverXbox.povDown().whileTrue(jointDescendCommand); + } + + public void puncherTestButtonBindings() { + //driverXbox.leftBumper().whileTrue(puncherBuildUpCommand); + //driverXbox.rightBumper().onTrue(testPuncherReleaseCommand); + + } + + public void elevatorTestButtonBindings() { + driverXbox.povLeft().whileTrue(testElevatorAscendCommand); + driverXbox.povRight().whileTrue(testElevatorDescendCommand); + } + + public void intakeButtonBindings() { + driverXbox.y().whileTrue(intakeCommand); //TESTAR + driverXbox.x().whileTrue(outtakeCommand); //TESTAR + driverXbox.b().whileTrue(intakeStopCommand); //TESTAR + } + + public void jointButtonBindings() { + driverXbox.povUp().whileTrue(jointAscendCommand); + driverXbox.povDown().whileTrue(jointDescendCommand); + } + + public void puncherButtonBindings() { + driverXbox.leftBumper().whileTrue(puncherBuildUpCommand); + driverXbox.rightBumper().onTrue(testPuncherReleaseCommand); + } + */ + public void elevatorButtonBindings() { + driverXbox.povLeft().whileTrue(elevatorAscendCommand); + driverXbox.povRight().whileTrue(elevatorDescendCommand); + } +} diff --git a/src/main/java/frc/robot/buttonBindings/OperatorButtonBindings.java b/src/main/java/frc/robot/buttonBindings/OperatorButtonBindings.java new file mode 100644 index 0000000..42334d2 --- /dev/null +++ b/src/main/java/frc/robot/buttonBindings/OperatorButtonBindings.java @@ -0,0 +1,15 @@ +package frc.robot.buttonBindings; + +import edu.wpi.first.wpilibj2.command.button.CommandXboxController; + +public class OperatorButtonBindings { + private final CommandXboxController operatorXbox; + + public OperatorButtonBindings(CommandXboxController operatorXbox) { + this.operatorXbox = operatorXbox; + } + + public void configureBindings() { + + } +} diff --git a/src/main/java/frc/robot/commands/swervedrive/auto/AutoBalanceCommand.java b/src/main/java/frc/robot/commands/swervedrive/auto/AutoBalanceCommand.java deleted file mode 100644 index 6919e45..0000000 --- a/src/main/java/frc/robot/commands/swervedrive/auto/AutoBalanceCommand.java +++ /dev/null @@ -1,86 +0,0 @@ -package frc.robot.commands.swervedrive.auto; - -import edu.wpi.first.math.MathUtil; -import edu.wpi.first.math.controller.PIDController; -import edu.wpi.first.math.geometry.Translation2d; -import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; -import edu.wpi.first.wpilibj2.command.Command; -import frc.robot.subsystems.swervedrive.SwerveSubsystem; - - -/** - * Auto Balance command using a simple PID controller. Created by Team 3512 - * ... - */ -public class AutoBalanceCommand extends Command -{ - - private final SwerveSubsystem swerveSubsystem; - private final PIDController controller; - - public AutoBalanceCommand(SwerveSubsystem swerveSubsystem) - { - this.swerveSubsystem = swerveSubsystem; - controller = new PIDController(1.0, 0.0, 0.0); - controller.setTolerance(1); - controller.setSetpoint(0.0); - // each subsystem used by the command must be passed into the - // addRequirements() method (which takes a vararg of Subsystem) - addRequirements(this.swerveSubsystem); - } - - /** - * The initial subroutine of a command. Called once when the command is initially scheduled. - */ - @Override - public void initialize() - { - - } - - /** - * The main body of a command. Called repeatedly while the command is scheduled. (That is, it is called repeatedly - * until {@link #isFinished()}) returns true.) - */ - @Override - public void execute() - { - SmartDashboard.putBoolean("At Tolerance", controller.atSetpoint()); - - double translationVal = MathUtil.clamp(controller.calculate(swerveSubsystem.getPitch().getDegrees(), 0.0), -0.5, - 0.5); - swerveSubsystem.drive(new Translation2d(translationVal, 0.0), 0.0, true); - } - - /** - *

- * Returns whether this command has finished. Once a command finishes -- indicated by this method returning true -- - * the scheduler will call its {@link #end(boolean)} method. - *

- * Returning false will result in the command never ending automatically. It may still be cancelled manually or - * interrupted by another command. Hard coding this command to always return true will result in the command executing - * once and finishing immediately. It is recommended to use * - * {@link edu.wpi.first.wpilibj2.command.InstantCommand InstantCommand} for such an operation. - *

- * - * @return whether this command has finished. - */ - @Override - public boolean isFinished() - { - return controller.atSetpoint(); - } - - /** - * The action to take when the command ends. Called when either the command finishes normally -- that is it is called - * when {@link #isFinished()} returns true -- or when it is interrupted/canceled. This is where you may want to wrap - * up loose ends, like shutting off a motor that was being used in the command. - * - * @param interrupted whether the command was interrupted/canceled - */ - @Override - public void end(boolean interrupted) - { - swerveSubsystem.lock(); - } -} diff --git a/src/main/java/frc/robot/commands/swervedrive/drivebase/AbsoluteDriveAdv.java b/src/main/java/frc/robot/commands/swervedrive/drivebase/AbsoluteDriveAdv.java index a92904f..0ec9d2a 100644 --- a/src/main/java/frc/robot/commands/swervedrive/drivebase/AbsoluteDriveAdv.java +++ b/src/main/java/frc/robot/commands/swervedrive/drivebase/AbsoluteDriveAdv.java @@ -130,7 +130,7 @@ public void execute() if (headingX == 0 && headingY == 0 && Math.abs(headingAdjust.getAsDouble()) > 0) { resetHeading = true; - swerve.drive(translation, (Constants.OperatorConstants.TURN_CONSTANT * -headingAdjust.getAsDouble()), true); + swerve.drive(translation, (Constants.HIDConstants.TURN_CONSTANT * -headingAdjust.getAsDouble()), true); } else { swerve.drive(translation, desiredSpeeds.omegaRadiansPerSecond, true); diff --git a/src/main/java/frc/robot/subsystems/ElevatorSubsystem.java b/src/main/java/frc/robot/subsystems/ElevatorSubsystem.java new file mode 100644 index 0000000..2a83a89 --- /dev/null +++ b/src/main/java/frc/robot/subsystems/ElevatorSubsystem.java @@ -0,0 +1,80 @@ +package frc.robot.subsystems; + +import edu.wpi.first.networktables.GenericEntry; +import edu.wpi.first.wpilibj.DigitalInput; +import edu.wpi.first.wpilibj.shuffleboard.BuiltInWidgets; +import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.Commands; +import edu.wpi.first.wpilibj2.command.ConditionalCommand; +import edu.wpi.first.wpilibj2.command.SubsystemBase; +import frc.robot.Constants; + +import com.ctre.phoenix.motorcontrol.can.TalonSRX; +import java.util.function.DoubleSupplier; + +import com.ctre.phoenix.motorcontrol.ControlMode; +import com.ctre.phoenix.motorcontrol.NeutralMode; + +public class ElevatorSubsystem extends SubsystemBase { + private final TalonSRX motor; + private final DigitalInput minLimitSwitch; + + private GenericEntry ascendDutyCycleOutValue; + private GenericEntry descendDutyCycleOutValue; + + public ElevatorSubsystem() { + motor = new TalonSRX(Constants.ElevatorConstants.MOTOR_CAN_ID); + motor.setNeutralMode(NeutralMode.Brake); + + minLimitSwitch = new DigitalInput(Constants.ElevatorConstants.LIMIT_SWITCH_DIO_PORT); + + if(Constants.DEV_MODE) { + ascendDutyCycleOutValue = Shuffleboard.getTab("Elevator Subsystem").add("Ascend: DutyCycleOut", 0) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + + descendDutyCycleOutValue = Shuffleboard.getTab("Elevator Subsystem").add("Descend: DutyCycleOut", 0) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + } + } + + public void stop() { + motor.set(ControlMode.PercentOutput, 0); + } + + public boolean isAtMin() { + return minLimitSwitch.get(); + } + + public void percentOut(double speed) { + motor.set(ControlMode.PercentOutput, speed); + } + + public Command percentOutCommand(DoubleSupplier speed) { + return Commands.startEnd(() -> this.percentOut(speed.getAsDouble()), this::stop, this); + } + + public Command descendCommand() { + return new ConditionalCommand(percentOutCommand(() -> -1), percentOutCommand(() -> 0), () -> !this.isAtMin()); + } + + public Command testDescendCommand() { + return Commands.startEnd(() -> this.percentOut(descendDutyCycleOutValue.getDouble(0)*(-1)), this::stop, this).until(this::isAtMin); + } + + public Command testAscendCommand() { + return Commands.startEnd(() -> this.percentOut(ascendDutyCycleOutValue.getDouble(0)), this::stop, this); + } + + public void debug() { + SmartDashboard.putBoolean("Elevator Subsystem/Limit Switch", minLimitSwitch.get()); + } + + @Override + public void periodic() { + if(Constants.DEV_MODE) { + this.debug(); + } + } +} \ No newline at end of file diff --git a/src/main/java/frc/robot/subsystems/IntakeSubsystem.java b/src/main/java/frc/robot/subsystems/IntakeSubsystem.java new file mode 100644 index 0000000..545743b --- /dev/null +++ b/src/main/java/frc/robot/subsystems/IntakeSubsystem.java @@ -0,0 +1,72 @@ +package frc.robot.subsystems; + +import java.util.function.DoubleSupplier; + +import com.ctre.phoenix.motorcontrol.NeutralMode; +import com.ctre.phoenix.motorcontrol.TalonSRXControlMode; +import com.ctre.phoenix.motorcontrol.can.TalonSRX; +import com.ctre.phoenix.motorcontrol.can.TalonSRXConfiguration; + +import edu.wpi.first.networktables.GenericEntry; +import edu.wpi.first.wpilibj.shuffleboard.BuiltInWidgets; +import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.Commands; +import edu.wpi.first.wpilibj2.command.SubsystemBase; +import frc.robot.Constants; + +public class IntakeSubsystem extends SubsystemBase { + private final TalonSRX intakeMotor; + + private GenericEntry intakeDutyCycleValue; + private GenericEntry outtakeDutyCycleValue; + + public IntakeSubsystem() { + intakeMotor = new TalonSRX(Constants.IntakeConstants.MOTOR_CAN_ID); + + TalonSRXConfiguration configs = new TalonSRXConfiguration(); + + intakeMotor.configAllSettings(configs); + intakeMotor.setNeutralMode(NeutralMode.Coast); + intakeMotor.setInverted(false); + + if(Constants.DEV_MODE) { + intakeDutyCycleValue = Shuffleboard.getTab("Intake Subsystem").add("Intake: DutyCycleOut", 0.3) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + + outtakeDutyCycleValue = Shuffleboard.getTab("Intake Subsystem").add("Outtake: DutyCycleOut", 0.6) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + } + } + + public void percentOut(double speed) { + intakeMotor.set(TalonSRXControlMode.PercentOutput, speed); + } + + public void stop() { + intakeMotor.set(TalonSRXControlMode.PercentOutput, 0); + } + + public Command percentOutCommand(DoubleSupplier speed) { + return Commands.startEnd(this::stop, () -> this.percentOut(speed.getAsDouble()), this); + } + + public Command testIntakeCommand() { + return Commands.startEnd(this::stop,() -> this.percentOut(-intakeDutyCycleValue.getDouble(0.3)), this); + } + + public Command testOuttakeCommand() { + return Commands.startEnd(this::stop, () -> this.percentOut(outtakeDutyCycleValue.getDouble(0.6)), this); + } + + public void debug() { + + } + + @Override + public void periodic() { + if(Constants.DEV_MODE) { + this.debug(); + } + } +} \ No newline at end of file diff --git a/src/main/java/frc/robot/subsystems/JointSubsystem.java b/src/main/java/frc/robot/subsystems/JointSubsystem.java new file mode 100644 index 0000000..2b8db09 --- /dev/null +++ b/src/main/java/frc/robot/subsystems/JointSubsystem.java @@ -0,0 +1,208 @@ +package frc.robot.subsystems; + +import java.util.function.DoubleSupplier; + +import com.ctre.phoenix.motorcontrol.ControlMode; +import com.ctre.phoenix.motorcontrol.FeedbackDevice; +import com.ctre.phoenix.motorcontrol.NeutralMode; +import com.ctre.phoenix.motorcontrol.TalonSRXControlMode; +import com.ctre.phoenix.motorcontrol.VictorSPXControlMode; +import com.ctre.phoenix.motorcontrol.can.TalonSRXConfiguration; +import com.ctre.phoenix.motorcontrol.can.VictorSPXConfiguration; +import com.ctre.phoenix.motorcontrol.can.WPI_TalonSRX; +import com.ctre.phoenix.motorcontrol.can.WPI_VictorSPX; +import edu.wpi.first.math.controller.PIDController; +import edu.wpi.first.networktables.GenericEntry; +import edu.wpi.first.wpilibj.DutyCycleEncoder; +import edu.wpi.first.wpilibj.shuffleboard.BuiltInWidgets; +import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.Commands; +import edu.wpi.first.wpilibj2.command.InstantCommand; +import edu.wpi.first.wpilibj2.command.SubsystemBase; +import frc.robot.Constants; + +public class JointSubsystem extends SubsystemBase { + private final WPI_TalonSRX jointLeftMotor; + private final WPI_VictorSPX jointRightMotor; + private final DutyCycleEncoder absoluteEncoder; + + private final PIDController masterController; + private final PIDController slaveController; + + private boolean absoluteEncoderConnected; + private int absoluteEncoderFrequency; + private double absoluteEncoderRaw; + private double absoluteEncoderAdjusted; + + private double analogEncoderRaw; + private double analogEncoderAdjusted; + + private GenericEntry absoluteEncoderMultiplierValue; + private GenericEntry absoluteEncoderOffsetValue; + + private GenericEntry analogEncoderMultiplierValue; + private GenericEntry analogEncoderOffsetValue; + + private GenericEntry setpointValue; + + private GenericEntry masterControllerProportionalValue; + private GenericEntry masterControllerIntegralValue; + private GenericEntry masterControllerDerivativeValue; + + private GenericEntry slaveControllerProportionalValue; + private GenericEntry slaveControllerIntegralValue; + private GenericEntry slaveControllerDerivativeValue; + + private GenericEntry dutyCycleOutValue; + + public JointSubsystem() { + jointLeftMotor = new WPI_TalonSRX(Constants.JointConstants.LEFT_MOTOR_CAN_ID); + jointRightMotor = new WPI_VictorSPX(Constants.JointConstants.RIGHT_MOTOR_CAN_ID); + + absoluteEncoder = new DutyCycleEncoder(Constants.JointConstants.RIGHT_ENCODER_DIO_PORT, 100, 0); + absoluteEncoder.setAssumedFrequency(975.6); + + //jointLeftMotor.getSensorCollection().setQuadraturePosition((int) Math.round(absoluteEncoder.get()), 0); + + masterController = new PIDController(0, 0, 0); + masterController.setTolerance(2); + + slaveController = new PIDController(0, 0, 0); + slaveController.setTolerance(0.2); + + TalonSRXConfiguration masterConfigs = new TalonSRXConfiguration(); + VictorSPXConfiguration slaveConfigs = new VictorSPXConfiguration(); + + jointLeftMotor.configAllSettings(masterConfigs); + jointRightMotor.configAllSettings(slaveConfigs); + + jointLeftMotor.setNeutralMode(NeutralMode.Brake); + jointRightMotor.setNeutralMode(NeutralMode.Brake); + + jointLeftMotor.setInverted(true); + jointRightMotor.setInverted(false); + + //jointRightMotor.follow(jointLeftMotor); + + if(Constants.DEV_MODE) { + absoluteEncoderMultiplierValue = Shuffleboard.getTab("Joint Subsystem").add("Absolute Encoder: Multipler", 1) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + + absoluteEncoderOffsetValue = Shuffleboard.getTab("Joint Subsystem").add("Absolute Encoder: Offset", 0) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + + analogEncoderMultiplierValue = Shuffleboard.getTab("Joint Subsystem").add("Analog Encoder: Multipler", 1) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + + analogEncoderOffsetValue = Shuffleboard.getTab("Joint Subsystem").add("Analog Encoder: Offset", 0) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + + setpointValue = Shuffleboard.getTab("Joint Subsystem").add("PID Controller: Setpoint", 0) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + + masterControllerProportionalValue = Shuffleboard.getTab("Joint Subsystem").add("Master: P", 0) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + masterControllerIntegralValue = Shuffleboard.getTab("Joint Subsystem").add("Master: I", 0) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + masterControllerDerivativeValue = Shuffleboard.getTab("Joint Subsystem").add("Master: D", 0) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + + slaveControllerProportionalValue = Shuffleboard.getTab("Joint Subsystem").add("Slave: P", 0) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + slaveControllerIntegralValue = Shuffleboard.getTab("Joint Subsystem").add("Slave: I", 0) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + slaveControllerDerivativeValue = Shuffleboard.getTab("Joint Subsystem").add("Slave: D", 0) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + dutyCycleOutValue = Shuffleboard.getTab("Joint Subsystem").add("DutyCycleOut", 0) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + + Shuffleboard.getTab("Joint Subsystem").add("Closed Loop Command", testClosedLoopCommand()); + Shuffleboard.getTab("Joint Subsystem").add("Update Controllers Parameters Command", testUpdateClosedLoopControllersCommand()); + } + } + + public void percentOut(double speed) { + jointLeftMotor.set(ControlMode.PercentOutput, speed); + jointRightMotor.set(ControlMode.PercentOutput, speed); + } + + public void stop() { + jointLeftMotor.set(ControlMode.PercentOutput, 0); + jointRightMotor.set(ControlMode.PercentOutput, 0); + } + + public boolean atSetpoint() { + return masterController.atSetpoint() && slaveController.atSetpoint(); + } + + public void masterClosedLoop(double setpoint) { + jointLeftMotor.set(TalonSRXControlMode.Position, masterController.calculate(analogEncoderAdjusted, setpoint)); + } + + public void slaveClosedLoop() { + jointRightMotor.set(VictorSPXControlMode.PercentOutput, slaveController.calculate(absoluteEncoderAdjusted, analogEncoderAdjusted)); + } + + public void positionClosedLoop(double setpoint) { + masterClosedLoop(setpoint); + slaveClosedLoop(); + } + + public Command percentOutCommand(DoubleSupplier speed) { + return Commands.startEnd(() -> this.percentOut(speed.getAsDouble()), this::stop, this); + } + + public Command closedLoopCommand(DoubleSupplier speed) { + return Commands.startEnd(() -> this.positionClosedLoop(speed.getAsDouble()), this::stop, this); + } + + public Command testClosedLoopCommand() { + return Commands.startEnd(() -> this.positionClosedLoop(setpointValue.getDouble(0)), this::stop, this).until(this::atSetpoint); + } + + public void updateClosedLoopControllersParameters() { + masterController.setPID(masterControllerProportionalValue.getDouble(0), masterControllerIntegralValue.getDouble(0), masterControllerDerivativeValue.getDouble(0)); + slaveController.setPID(slaveControllerProportionalValue.getDouble(0), slaveControllerIntegralValue.getDouble(0), slaveControllerDerivativeValue.getDouble(0)); + } + + public boolean isSafeBuildUpAngle() { + return absoluteEncoderAdjusted < 60; + } + + public boolean isAngleLower() { + return absoluteEncoderAdjusted < 70; + } + + public boolean isAngleHigher() { + return absoluteEncoderAdjusted > 60; + } + + public Command testOpenLoopCommand() { + return this.runEnd(() -> this.percentOut(dutyCycleOutValue.getDouble(0)), this::stop); + } + + public Command testUpdateClosedLoopControllersCommand() { + return new InstantCommand(this::updateClosedLoopControllersParameters, this); + } + + public void debug() { + absoluteEncoderConnected = absoluteEncoder.isConnected(); + absoluteEncoderFrequency = absoluteEncoder.getFrequency(); + absoluteEncoderAdjusted = ((absoluteEncoder.get()) + absoluteEncoderOffsetValue.getDouble(0))*(absoluteEncoderMultiplierValue.getDouble(1)); + absoluteEncoderRaw = (absoluteEncoder.get()); + + SmartDashboard.putBoolean("Joint Subsystem/Absolute Encoder/Connected", absoluteEncoderConnected); + SmartDashboard.putNumber("Joint Subsystem/Absolute Encoder/Frequency", absoluteEncoderFrequency); + SmartDashboard.putNumber("Joint Subsystem/Absolute Encoder/Adjusted", absoluteEncoderAdjusted); + SmartDashboard.putNumber("Joint Subsystem/Absolute Encoder/Raw", absoluteEncoderRaw); + } + + @Override + public void periodic() { + if(Constants.DEV_MODE) { + this.debug(); + } + } +} diff --git a/src/main/java/frc/robot/subsystems/LimelightHelpers.java b/src/main/java/frc/robot/subsystems/LimelightHelpers.java new file mode 100644 index 0000000..294415b --- /dev/null +++ b/src/main/java/frc/robot/subsystems/LimelightHelpers.java @@ -0,0 +1,1700 @@ +//LimelightHelpers v1.12 (REQUIRES LLOS 2025.0 OR LATER) + +package frc.robot.subsystems; + +import edu.wpi.first.networktables.DoubleArrayEntry; +import edu.wpi.first.networktables.NetworkTable; +import edu.wpi.first.networktables.NetworkTableEntry; +import edu.wpi.first.networktables.NetworkTableInstance; +import edu.wpi.first.networktables.TimestampedDoubleArray; +import frc.robot.subsystems.LimelightHelpers.LimelightResults; +import frc.robot.subsystems.LimelightHelpers.PoseEstimate; +import edu.wpi.first.math.geometry.Pose2d; +import edu.wpi.first.math.geometry.Pose3d; +import edu.wpi.first.math.geometry.Rotation2d; +import edu.wpi.first.math.geometry.Translation3d; +import edu.wpi.first.math.util.Units; +import edu.wpi.first.math.geometry.Rotation3d; +import edu.wpi.first.math.geometry.Translation2d; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Arrays; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonFormat.Shape; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.concurrent.ConcurrentHashMap; + +/** + * LimelightHelpers provides static methods and classes for interfacing with Limelight vision cameras in FRC. + * This library supports all Limelight features including AprilTag tracking, Neural Networks, and standard color/retroreflective tracking. + */ +public class LimelightHelpers { + + private static final Map doubleArrayEntries = new ConcurrentHashMap<>(); + + /** + * Represents a Color/Retroreflective Target Result extracted from JSON Output + */ + public static class LimelightTarget_Retro { + + @JsonProperty("t6c_ts") + private double[] cameraPose_TargetSpace; + + @JsonProperty("t6r_fs") + private double[] robotPose_FieldSpace; + + @JsonProperty("t6r_ts") + private double[] robotPose_TargetSpace; + + @JsonProperty("t6t_cs") + private double[] targetPose_CameraSpace; + + @JsonProperty("t6t_rs") + private double[] targetPose_RobotSpace; + + public Pose3d getCameraPose_TargetSpace() + { + return toPose3D(cameraPose_TargetSpace); + } + public Pose3d getRobotPose_FieldSpace() + { + return toPose3D(robotPose_FieldSpace); + } + public Pose3d getRobotPose_TargetSpace() + { + return toPose3D(robotPose_TargetSpace); + } + public Pose3d getTargetPose_CameraSpace() + { + return toPose3D(targetPose_CameraSpace); + } + public Pose3d getTargetPose_RobotSpace() + { + return toPose3D(targetPose_RobotSpace); + } + + public Pose2d getCameraPose_TargetSpace2D() + { + return toPose2D(cameraPose_TargetSpace); + } + public Pose2d getRobotPose_FieldSpace2D() + { + return toPose2D(robotPose_FieldSpace); + } + public Pose2d getRobotPose_TargetSpace2D() + { + return toPose2D(robotPose_TargetSpace); + } + public Pose2d getTargetPose_CameraSpace2D() + { + return toPose2D(targetPose_CameraSpace); + } + public Pose2d getTargetPose_RobotSpace2D() + { + return toPose2D(targetPose_RobotSpace); + } + + @JsonProperty("ta") + public double ta; + + @JsonProperty("tx") + public double tx; + + @JsonProperty("ty") + public double ty; + + @JsonProperty("txp") + public double tx_pixels; + + @JsonProperty("typ") + public double ty_pixels; + + @JsonProperty("tx_nocross") + public double tx_nocrosshair; + + @JsonProperty("ty_nocross") + public double ty_nocrosshair; + + @JsonProperty("ts") + public double ts; + + public LimelightTarget_Retro() { + cameraPose_TargetSpace = new double[6]; + robotPose_FieldSpace = new double[6]; + robotPose_TargetSpace = new double[6]; + targetPose_CameraSpace = new double[6]; + targetPose_RobotSpace = new double[6]; + } + + } + + /** + * Represents an AprilTag/Fiducial Target Result extracted from JSON Output + */ + public static class LimelightTarget_Fiducial { + + @JsonProperty("fID") + public double fiducialID; + + @JsonProperty("fam") + public String fiducialFamily; + + @JsonProperty("t6c_ts") + private double[] cameraPose_TargetSpace; + + @JsonProperty("t6r_fs") + private double[] robotPose_FieldSpace; + + @JsonProperty("t6r_ts") + private double[] robotPose_TargetSpace; + + @JsonProperty("t6t_cs") + private double[] targetPose_CameraSpace; + + @JsonProperty("t6t_rs") + private double[] targetPose_RobotSpace; + + public Pose3d getCameraPose_TargetSpace() + { + return toPose3D(cameraPose_TargetSpace); + } + public Pose3d getRobotPose_FieldSpace() + { + return toPose3D(robotPose_FieldSpace); + } + public Pose3d getRobotPose_TargetSpace() + { + return toPose3D(robotPose_TargetSpace); + } + public Pose3d getTargetPose_CameraSpace() + { + return toPose3D(targetPose_CameraSpace); + } + public Pose3d getTargetPose_RobotSpace() + { + return toPose3D(targetPose_RobotSpace); + } + + public Pose2d getCameraPose_TargetSpace2D() + { + return toPose2D(cameraPose_TargetSpace); + } + public Pose2d getRobotPose_FieldSpace2D() + { + return toPose2D(robotPose_FieldSpace); + } + public Pose2d getRobotPose_TargetSpace2D() + { + return toPose2D(robotPose_TargetSpace); + } + public Pose2d getTargetPose_CameraSpace2D() + { + return toPose2D(targetPose_CameraSpace); + } + public Pose2d getTargetPose_RobotSpace2D() + { + return toPose2D(targetPose_RobotSpace); + } + + @JsonProperty("ta") + public double ta; + + @JsonProperty("tx") + public double tx; + + @JsonProperty("ty") + public double ty; + + @JsonProperty("txp") + public double tx_pixels; + + @JsonProperty("typ") + public double ty_pixels; + + @JsonProperty("tx_nocross") + public double tx_nocrosshair; + + @JsonProperty("ty_nocross") + public double ty_nocrosshair; + + @JsonProperty("ts") + public double ts; + + public LimelightTarget_Fiducial() { + cameraPose_TargetSpace = new double[6]; + robotPose_FieldSpace = new double[6]; + robotPose_TargetSpace = new double[6]; + targetPose_CameraSpace = new double[6]; + targetPose_RobotSpace = new double[6]; + } + } + + /** + * Represents a Barcode Target Result extracted from JSON Output + */ + public static class LimelightTarget_Barcode { + + /** + * Barcode family type (e.g. "QR", "DataMatrix", etc.) + */ + @JsonProperty("fam") + public String family; + + /** + * Gets the decoded data content of the barcode + */ + @JsonProperty("data") + public String data; + + @JsonProperty("txp") + public double tx_pixels; + + @JsonProperty("typ") + public double ty_pixels; + + @JsonProperty("tx") + public double tx; + + @JsonProperty("ty") + public double ty; + + @JsonProperty("tx_nocross") + public double tx_nocrosshair; + + @JsonProperty("ty_nocross") + public double ty_nocrosshair; + + @JsonProperty("ta") + public double ta; + + @JsonProperty("pts") + public double[][] corners; + + public LimelightTarget_Barcode() { + } + + public String getFamily() { + return family; + } + } + + /** + * Represents a Neural Classifier Pipeline Result extracted from JSON Output + */ + public static class LimelightTarget_Classifier { + + @JsonProperty("class") + public String className; + + @JsonProperty("classID") + public double classID; + + @JsonProperty("conf") + public double confidence; + + @JsonProperty("zone") + public double zone; + + @JsonProperty("tx") + public double tx; + + @JsonProperty("txp") + public double tx_pixels; + + @JsonProperty("ty") + public double ty; + + @JsonProperty("typ") + public double ty_pixels; + + public LimelightTarget_Classifier() { + } + } + + /** + * Represents a Neural Detector Pipeline Result extracted from JSON Output + */ + public static class LimelightTarget_Detector { + + @JsonProperty("class") + public String className; + + @JsonProperty("classID") + public double classID; + + @JsonProperty("conf") + public double confidence; + + @JsonProperty("ta") + public double ta; + + @JsonProperty("tx") + public double tx; + + @JsonProperty("ty") + public double ty; + + @JsonProperty("txp") + public double tx_pixels; + + @JsonProperty("typ") + public double ty_pixels; + + @JsonProperty("tx_nocross") + public double tx_nocrosshair; + + @JsonProperty("ty_nocross") + public double ty_nocrosshair; + + public LimelightTarget_Detector() { + } + } + + /** + * Limelight Results object, parsed from a Limelight's JSON results output. + */ + public static class LimelightResults { + + public String error; + + @JsonProperty("pID") + public double pipelineID; + + @JsonProperty("tl") + public double latency_pipeline; + + @JsonProperty("cl") + public double latency_capture; + + public double latency_jsonParse; + + @JsonProperty("ts") + public double timestamp_LIMELIGHT_publish; + + @JsonProperty("ts_rio") + public double timestamp_RIOFPGA_capture; + + @JsonProperty("v") + @JsonFormat(shape = Shape.NUMBER) + public boolean valid; + + @JsonProperty("botpose") + public double[] botpose; + + @JsonProperty("botpose_wpired") + public double[] botpose_wpired; + + @JsonProperty("botpose_wpiblue") + public double[] botpose_wpiblue; + + @JsonProperty("botpose_tagcount") + public double botpose_tagcount; + + @JsonProperty("botpose_span") + public double botpose_span; + + @JsonProperty("botpose_avgdist") + public double botpose_avgdist; + + @JsonProperty("botpose_avgarea") + public double botpose_avgarea; + + @JsonProperty("t6c_rs") + public double[] camerapose_robotspace; + + public Pose3d getBotPose3d() { + return toPose3D(botpose); + } + + public Pose3d getBotPose3d_wpiRed() { + return toPose3D(botpose_wpired); + } + + public Pose3d getBotPose3d_wpiBlue() { + return toPose3D(botpose_wpiblue); + } + + public Pose2d getBotPose2d() { + return toPose2D(botpose); + } + + public Pose2d getBotPose2d_wpiRed() { + return toPose2D(botpose_wpired); + } + + public Pose2d getBotPose2d_wpiBlue() { + return toPose2D(botpose_wpiblue); + } + + @JsonProperty("Retro") + public LimelightTarget_Retro[] targets_Retro; + + @JsonProperty("Fiducial") + public LimelightTarget_Fiducial[] targets_Fiducials; + + @JsonProperty("Classifier") + public LimelightTarget_Classifier[] targets_Classifier; + + @JsonProperty("Detector") + public LimelightTarget_Detector[] targets_Detector; + + @JsonProperty("Barcode") + public LimelightTarget_Barcode[] targets_Barcode; + + public LimelightResults() { + botpose = new double[6]; + botpose_wpired = new double[6]; + botpose_wpiblue = new double[6]; + camerapose_robotspace = new double[6]; + targets_Retro = new LimelightTarget_Retro[0]; + targets_Fiducials = new LimelightTarget_Fiducial[0]; + targets_Classifier = new LimelightTarget_Classifier[0]; + targets_Detector = new LimelightTarget_Detector[0]; + targets_Barcode = new LimelightTarget_Barcode[0]; + + } + + + } + + /** + * Represents a Limelight Raw Fiducial result from Limelight's NetworkTables output. + */ + public static class RawFiducial { + public int id = 0; + public double txnc = 0; + public double tync = 0; + public double ta = 0; + public double distToCamera = 0; + public double distToRobot = 0; + public double ambiguity = 0; + + + public RawFiducial(int id, double txnc, double tync, double ta, double distToCamera, double distToRobot, double ambiguity) { + this.id = id; + this.txnc = txnc; + this.tync = tync; + this.ta = ta; + this.distToCamera = distToCamera; + this.distToRobot = distToRobot; + this.ambiguity = ambiguity; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + RawFiducial other = (RawFiducial) obj; + return id == other.id && + Double.compare(txnc, other.txnc) == 0 && + Double.compare(tync, other.tync) == 0 && + Double.compare(ta, other.ta) == 0 && + Double.compare(distToCamera, other.distToCamera) == 0 && + Double.compare(distToRobot, other.distToRobot) == 0 && + Double.compare(ambiguity, other.ambiguity) == 0; + } + + } + + /** + * Represents a Limelight Raw Neural Detector result from Limelight's NetworkTables output. + */ + public static class RawDetection { + public int classId = 0; + public double txnc = 0; + public double tync = 0; + public double ta = 0; + public double corner0_X = 0; + public double corner0_Y = 0; + public double corner1_X = 0; + public double corner1_Y = 0; + public double corner2_X = 0; + public double corner2_Y = 0; + public double corner3_X = 0; + public double corner3_Y = 0; + + + public RawDetection(int classId, double txnc, double tync, double ta, + double corner0_X, double corner0_Y, + double corner1_X, double corner1_Y, + double corner2_X, double corner2_Y, + double corner3_X, double corner3_Y ) { + this.classId = classId; + this.txnc = txnc; + this.tync = tync; + this.ta = ta; + this.corner0_X = corner0_X; + this.corner0_Y = corner0_Y; + this.corner1_X = corner1_X; + this.corner1_Y = corner1_Y; + this.corner2_X = corner2_X; + this.corner2_Y = corner2_Y; + this.corner3_X = corner3_X; + this.corner3_Y = corner3_Y; + } + } + + /** + * Represents a 3D Pose Estimate. + */ + public static class PoseEstimate { + public Pose2d pose; + public double timestampSeconds; + public double latency; + public int tagCount; + public double tagSpan; + public double avgTagDist; + public double avgTagArea; + + public RawFiducial[] rawFiducials; + public boolean isMegaTag2; + + /** + * Instantiates a PoseEstimate object with default values + */ + public PoseEstimate() { + this.pose = new Pose2d(); + this.timestampSeconds = 0; + this.latency = 0; + this.tagCount = 0; + this.tagSpan = 0; + this.avgTagDist = 0; + this.avgTagArea = 0; + this.rawFiducials = new RawFiducial[]{}; + this.isMegaTag2 = false; + } + + public PoseEstimate(Pose2d pose, double timestampSeconds, double latency, + int tagCount, double tagSpan, double avgTagDist, + double avgTagArea, RawFiducial[] rawFiducials, boolean isMegaTag2) { + + this.pose = pose; + this.timestampSeconds = timestampSeconds; + this.latency = latency; + this.tagCount = tagCount; + this.tagSpan = tagSpan; + this.avgTagDist = avgTagDist; + this.avgTagArea = avgTagArea; + this.rawFiducials = rawFiducials; + this.isMegaTag2 = isMegaTag2; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + PoseEstimate that = (PoseEstimate) obj; + // We don't compare the timestampSeconds as it isn't relevant for equality and makes + // unit testing harder + return Double.compare(that.latency, latency) == 0 + && tagCount == that.tagCount + && Double.compare(that.tagSpan, tagSpan) == 0 + && Double.compare(that.avgTagDist, avgTagDist) == 0 + && Double.compare(that.avgTagArea, avgTagArea) == 0 + && pose.equals(that.pose) + && Arrays.equals(rawFiducials, that.rawFiducials); + } + + } + + /** + * Encapsulates the state of an internal Limelight IMU. + */ + public static class IMUData { + public double robotYaw = 0.0; + public double Roll = 0.0; + public double Pitch = 0.0; + public double Yaw = 0.0; + public double gyroX = 0.0; + public double gyroY = 0.0; + public double gyroZ = 0.0; + public double accelX = 0.0; + public double accelY = 0.0; + public double accelZ = 0.0; + + public IMUData() {} + + public IMUData(double[] imuData) { + if (imuData != null && imuData.length >= 10) { + this.robotYaw = imuData[0]; + this.Roll = imuData[1]; + this.Pitch = imuData[2]; + this.Yaw = imuData[3]; + this.gyroX = imuData[4]; + this.gyroY = imuData[5]; + this.gyroZ = imuData[6]; + this.accelX = imuData[7]; + this.accelY = imuData[8]; + this.accelZ = imuData[9]; + } + } + } + + + private static ObjectMapper mapper; + + /** + * Print JSON Parse time to the console in milliseconds + */ + static boolean profileJSON = false; + + static final String sanitizeName(String name) { + if ("".equals(name) || name == null) { + return "limelight"; + } + return name; + } + + /** + * Takes a 6-length array of pose data and converts it to a Pose3d object. + * Array format: [x, y, z, roll, pitch, yaw] where angles are in degrees. + * @param inData Array containing pose data [x, y, z, roll, pitch, yaw] + * @return Pose3d object representing the pose, or empty Pose3d if invalid data + */ + public static Pose3d toPose3D(double[] inData){ + if(inData.length < 6) + { + //System.err.println("Bad LL 3D Pose Data!"); + return new Pose3d(); + } + return new Pose3d( + new Translation3d(inData[0], inData[1], inData[2]), + new Rotation3d(Units.degreesToRadians(inData[3]), Units.degreesToRadians(inData[4]), + Units.degreesToRadians(inData[5]))); + } + + /** + * Takes a 6-length array of pose data and converts it to a Pose2d object. + * Uses only x, y, and yaw components, ignoring z, roll, and pitch. + * Array format: [x, y, z, roll, pitch, yaw] where angles are in degrees. + * @param inData Array containing pose data [x, y, z, roll, pitch, yaw] + * @return Pose2d object representing the pose, or empty Pose2d if invalid data + */ + public static Pose2d toPose2D(double[] inData){ + if(inData.length < 6) + { + //System.err.println("Bad LL 2D Pose Data!"); + return new Pose2d(); + } + Translation2d tran2d = new Translation2d(inData[0], inData[1]); + Rotation2d r2d = new Rotation2d(Units.degreesToRadians(inData[5])); + return new Pose2d(tran2d, r2d); + } + + /** + * Converts a Pose3d object to an array of doubles in the format [x, y, z, roll, pitch, yaw]. + * Translation components are in meters, rotation components are in degrees. + * + * @param pose The Pose3d object to convert + * @return A 6-element array containing [x, y, z, roll, pitch, yaw] + */ + public static double[] pose3dToArray(Pose3d pose) { + double[] result = new double[6]; + result[0] = pose.getTranslation().getX(); + result[1] = pose.getTranslation().getY(); + result[2] = pose.getTranslation().getZ(); + result[3] = Units.radiansToDegrees(pose.getRotation().getX()); + result[4] = Units.radiansToDegrees(pose.getRotation().getY()); + result[5] = Units.radiansToDegrees(pose.getRotation().getZ()); + return result; + } + + /** + * Converts a Pose2d object to an array of doubles in the format [x, y, z, roll, pitch, yaw]. + * Translation components are in meters, rotation components are in degrees. + * Note: z, roll, and pitch will be 0 since Pose2d only contains x, y, and yaw. + * + * @param pose The Pose2d object to convert + * @return A 6-element array containing [x, y, 0, 0, 0, yaw] + */ + public static double[] pose2dToArray(Pose2d pose) { + double[] result = new double[6]; + result[0] = pose.getTranslation().getX(); + result[1] = pose.getTranslation().getY(); + result[2] = 0; + result[3] = Units.radiansToDegrees(0); + result[4] = Units.radiansToDegrees(0); + result[5] = Units.radiansToDegrees(pose.getRotation().getRadians()); + return result; + } + + private static double extractArrayEntry(double[] inData, int position){ + if(inData.length < position+1) + { + return 0; + } + return inData[position]; + } + + private static PoseEstimate getBotPoseEstimate(String limelightName, String entryName, boolean isMegaTag2) { + DoubleArrayEntry poseEntry = LimelightHelpers.getLimelightDoubleArrayEntry(limelightName, entryName); + + TimestampedDoubleArray tsValue = poseEntry.getAtomic(); + double[] poseArray = tsValue.value; + long timestamp = tsValue.timestamp; + + if (poseArray.length == 0) { + // Handle the case where no data is available + return null; // or some default PoseEstimate + } + + var pose = toPose2D(poseArray); + double latency = extractArrayEntry(poseArray, 6); + int tagCount = (int)extractArrayEntry(poseArray, 7); + double tagSpan = extractArrayEntry(poseArray, 8); + double tagDist = extractArrayEntry(poseArray, 9); + double tagArea = extractArrayEntry(poseArray, 10); + + // Convert server timestamp from microseconds to seconds and adjust for latency + double adjustedTimestamp = (timestamp / 1000000.0) - (latency / 1000.0); + + RawFiducial[] rawFiducials = new RawFiducial[tagCount]; + int valsPerFiducial = 7; + int expectedTotalVals = 11 + valsPerFiducial * tagCount; + + if (poseArray.length != expectedTotalVals) { + // Don't populate fiducials + } else { + for(int i = 0; i < tagCount; i++) { + int baseIndex = 11 + (i * valsPerFiducial); + int id = (int)poseArray[baseIndex]; + double txnc = poseArray[baseIndex + 1]; + double tync = poseArray[baseIndex + 2]; + double ta = poseArray[baseIndex + 3]; + double distToCamera = poseArray[baseIndex + 4]; + double distToRobot = poseArray[baseIndex + 5]; + double ambiguity = poseArray[baseIndex + 6]; + rawFiducials[i] = new RawFiducial(id, txnc, tync, ta, distToCamera, distToRobot, ambiguity); + } + } + + return new PoseEstimate(pose, adjustedTimestamp, latency, tagCount, tagSpan, tagDist, tagArea, rawFiducials, isMegaTag2); + } + + /** + * Gets the latest raw fiducial/AprilTag detection results from NetworkTables. + * + * @param limelightName Name/identifier of the Limelight + * @return Array of RawFiducial objects containing detection details + */ + public static RawFiducial[] getRawFiducials(String limelightName) { + var entry = LimelightHelpers.getLimelightNTTableEntry(limelightName, "rawfiducials"); + var rawFiducialArray = entry.getDoubleArray(new double[0]); + int valsPerEntry = 7; + if (rawFiducialArray.length % valsPerEntry != 0) { + return new RawFiducial[0]; + } + + int numFiducials = rawFiducialArray.length / valsPerEntry; + RawFiducial[] rawFiducials = new RawFiducial[numFiducials]; + + for (int i = 0; i < numFiducials; i++) { + int baseIndex = i * valsPerEntry; + int id = (int) extractArrayEntry(rawFiducialArray, baseIndex); + double txnc = extractArrayEntry(rawFiducialArray, baseIndex + 1); + double tync = extractArrayEntry(rawFiducialArray, baseIndex + 2); + double ta = extractArrayEntry(rawFiducialArray, baseIndex + 3); + double distToCamera = extractArrayEntry(rawFiducialArray, baseIndex + 4); + double distToRobot = extractArrayEntry(rawFiducialArray, baseIndex + 5); + double ambiguity = extractArrayEntry(rawFiducialArray, baseIndex + 6); + + rawFiducials[i] = new RawFiducial(id, txnc, tync, ta, distToCamera, distToRobot, ambiguity); + } + + return rawFiducials; + } + + /** + * Gets the latest raw neural detector results from NetworkTables + * + * @param limelightName Name/identifier of the Limelight + * @return Array of RawDetection objects containing detection details + */ + public static RawDetection[] getRawDetections(String limelightName) { + var entry = LimelightHelpers.getLimelightNTTableEntry(limelightName, "rawdetections"); + var rawDetectionArray = entry.getDoubleArray(new double[0]); + int valsPerEntry = 12; + if (rawDetectionArray.length % valsPerEntry != 0) { + return new RawDetection[0]; + } + + int numDetections = rawDetectionArray.length / valsPerEntry; + RawDetection[] rawDetections = new RawDetection[numDetections]; + + for (int i = 0; i < numDetections; i++) { + int baseIndex = i * valsPerEntry; // Starting index for this detection's data + int classId = (int) extractArrayEntry(rawDetectionArray, baseIndex); + double txnc = extractArrayEntry(rawDetectionArray, baseIndex + 1); + double tync = extractArrayEntry(rawDetectionArray, baseIndex + 2); + double ta = extractArrayEntry(rawDetectionArray, baseIndex + 3); + double corner0_X = extractArrayEntry(rawDetectionArray, baseIndex + 4); + double corner0_Y = extractArrayEntry(rawDetectionArray, baseIndex + 5); + double corner1_X = extractArrayEntry(rawDetectionArray, baseIndex + 6); + double corner1_Y = extractArrayEntry(rawDetectionArray, baseIndex + 7); + double corner2_X = extractArrayEntry(rawDetectionArray, baseIndex + 8); + double corner2_Y = extractArrayEntry(rawDetectionArray, baseIndex + 9); + double corner3_X = extractArrayEntry(rawDetectionArray, baseIndex + 10); + double corner3_Y = extractArrayEntry(rawDetectionArray, baseIndex + 11); + + rawDetections[i] = new RawDetection(classId, txnc, tync, ta, corner0_X, corner0_Y, corner1_X, corner1_Y, corner2_X, corner2_Y, corner3_X, corner3_Y); + } + + return rawDetections; + } + + /** + * Prints detailed information about a PoseEstimate to standard output. + * Includes timestamp, latency, tag count, tag span, average tag distance, + * average tag area, and detailed information about each detected fiducial. + * + * @param pose The PoseEstimate object to print. If null, prints "No PoseEstimate available." + */ + public static void printPoseEstimate(PoseEstimate pose) { + if (pose == null) { + System.out.println("No PoseEstimate available."); + return; + } + + System.out.printf("Pose Estimate Information:%n"); + System.out.printf("Timestamp (Seconds): %.3f%n", pose.timestampSeconds); + System.out.printf("Latency: %.3f ms%n", pose.latency); + System.out.printf("Tag Count: %d%n", pose.tagCount); + System.out.printf("Tag Span: %.2f meters%n", pose.tagSpan); + System.out.printf("Average Tag Distance: %.2f meters%n", pose.avgTagDist); + System.out.printf("Average Tag Area: %.2f%% of image%n", pose.avgTagArea); + System.out.printf("Is MegaTag2: %b%n", pose.isMegaTag2); + System.out.println(); + + if (pose.rawFiducials == null || pose.rawFiducials.length == 0) { + System.out.println("No RawFiducials data available."); + return; + } + + System.out.println("Raw Fiducials Details:"); + for (int i = 0; i < pose.rawFiducials.length; i++) { + RawFiducial fiducial = pose.rawFiducials[i]; + System.out.printf(" Fiducial #%d:%n", i + 1); + System.out.printf(" ID: %d%n", fiducial.id); + System.out.printf(" TXNC: %.2f%n", fiducial.txnc); + System.out.printf(" TYNC: %.2f%n", fiducial.tync); + System.out.printf(" TA: %.2f%n", fiducial.ta); + System.out.printf(" Distance to Camera: %.2f meters%n", fiducial.distToCamera); + System.out.printf(" Distance to Robot: %.2f meters%n", fiducial.distToRobot); + System.out.printf(" Ambiguity: %.2f%n", fiducial.ambiguity); + System.out.println(); + } + } + + public static Boolean validPoseEstimate(PoseEstimate pose) { + return pose != null && pose.rawFiducials != null && pose.rawFiducials.length != 0; + } + + public static NetworkTable getLimelightNTTable(String tableName) { + return NetworkTableInstance.getDefault().getTable(sanitizeName(tableName)); + } + + public static void Flush() { + NetworkTableInstance.getDefault().flush(); + } + + public static NetworkTableEntry getLimelightNTTableEntry(String tableName, String entryName) { + return getLimelightNTTable(tableName).getEntry(entryName); + } + + public static DoubleArrayEntry getLimelightDoubleArrayEntry(String tableName, String entryName) { + String key = tableName + "/" + entryName; + return doubleArrayEntries.computeIfAbsent(key, k -> { + NetworkTable table = getLimelightNTTable(tableName); + return table.getDoubleArrayTopic(entryName).getEntry(new double[0]); + }); + } + + public static double getLimelightNTDouble(String tableName, String entryName) { + return getLimelightNTTableEntry(tableName, entryName).getDouble(0.0); + } + + public static void setLimelightNTDouble(String tableName, String entryName, double val) { + getLimelightNTTableEntry(tableName, entryName).setDouble(val); + } + + public static void setLimelightNTDoubleArray(String tableName, String entryName, double[] val) { + getLimelightNTTableEntry(tableName, entryName).setDoubleArray(val); + } + + public static double[] getLimelightNTDoubleArray(String tableName, String entryName) { + return getLimelightNTTableEntry(tableName, entryName).getDoubleArray(new double[0]); + } + + + public static String getLimelightNTString(String tableName, String entryName) { + return getLimelightNTTableEntry(tableName, entryName).getString(""); + } + + public static String[] getLimelightNTStringArray(String tableName, String entryName) { + return getLimelightNTTableEntry(tableName, entryName).getStringArray(new String[0]); + } + + + public static URL getLimelightURLString(String tableName, String request) { + String urlString = "http://" + sanitizeName(tableName) + ".local:5807/" + request; + URL url; + try { + url = new URL(urlString); + return url; + } catch (MalformedURLException e) { + System.err.println("bad LL URL"); + } + return null; + } + ///// + ///// + + /** + * Does the Limelight have a valid target? + * @param limelightName Name of the Limelight camera ("" for default) + * @return True if a valid target is present, false otherwise + */ + public static boolean getTV(String limelightName) { + return 1.0 == getLimelightNTDouble(limelightName, "tv"); + } + + /** + * Gets the horizontal offset from the crosshair to the target in degrees. + * @param limelightName Name of the Limelight camera ("" for default) + * @return Horizontal offset angle in degrees + */ + public static double getTX(String limelightName) { + return getLimelightNTDouble(limelightName, "tx"); + } + + /** + * Gets the vertical offset from the crosshair to the target in degrees. + * @param limelightName Name of the Limelight camera ("" for default) + * @return Vertical offset angle in degrees + */ + public static double getTY(String limelightName) { + return getLimelightNTDouble(limelightName, "ty"); + } + + /** + * Gets the horizontal offset from the principal pixel/point to the target in degrees. This is the most accurate 2d metric if you are using a calibrated camera and you don't need adjustable crosshair functionality. + * @param limelightName Name of the Limelight camera ("" for default) + * @return Horizontal offset angle in degrees + */ + public static double getTXNC(String limelightName) { + return getLimelightNTDouble(limelightName, "txnc"); + } + + /** + * Gets the vertical offset from the principal pixel/point to the target in degrees. This is the most accurate 2d metric if you are using a calibrated camera and you don't need adjustable crosshair functionality. + * @param limelightName Name of the Limelight camera ("" for default) + * @return Vertical offset angle in degrees + */ + public static double getTYNC(String limelightName) { + return getLimelightNTDouble(limelightName, "tync"); + } + + /** + * Gets the target area as a percentage of the image (0-100%). + * @param limelightName Name of the Limelight camera ("" for default) + * @return Target area percentage (0-100) + */ + public static double getTA(String limelightName) { + return getLimelightNTDouble(limelightName, "ta"); + } + + /** + * T2D is an array that contains several targeting metrcis + * @param limelightName Name of the Limelight camera + * @return Array containing [targetValid, targetCount, targetLatency, captureLatency, tx, ty, txnc, tync, ta, tid, targetClassIndexDetector, + * targetClassIndexClassifier, targetLongSidePixels, targetShortSidePixels, targetHorizontalExtentPixels, targetVerticalExtentPixels, targetSkewDegrees] + */ + public static double[] getT2DArray(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "t2d"); + } + + /** + * Gets the number of targets currently detected. + * @param limelightName Name of the Limelight camera + * @return Number of detected targets + */ + public static int getTargetCount(String limelightName) { + double[] t2d = getT2DArray(limelightName); + if(t2d.length == 17) + { + return (int)t2d[1]; + } + return 0; + } + + /** + * Gets the classifier class index from the currently running neural classifier pipeline + * @param limelightName Name of the Limelight camera + * @return Class index from classifier pipeline + */ + public static int getClassifierClassIndex (String limelightName) { + double[] t2d = getT2DArray(limelightName); + if(t2d.length == 17) + { + return (int)t2d[10]; + } + return 0; + } + + /** + * Gets the detector class index from the primary result of the currently running neural detector pipeline. + * @param limelightName Name of the Limelight camera + * @return Class index from detector pipeline + */ + public static int getDetectorClassIndex (String limelightName) { + double[] t2d = getT2DArray(limelightName); + if(t2d.length == 17) + { + return (int)t2d[11]; + } + return 0; + } + + /** + * Gets the current neural classifier result class name. + * @param limelightName Name of the Limelight camera + * @return Class name string from classifier pipeline + */ + public static String getClassifierClass (String limelightName) { + return getLimelightNTString(limelightName, "tcclass"); + } + + /** + * Gets the primary neural detector result class name. + * @param limelightName Name of the Limelight camera + * @return Class name string from detector pipeline + */ + public static String getDetectorClass (String limelightName) { + return getLimelightNTString(limelightName, "tdclass"); + } + + /** + * Gets the pipeline's processing latency contribution. + * @param limelightName Name of the Limelight camera + * @return Pipeline latency in milliseconds + */ + public static double getLatency_Pipeline(String limelightName) { + return getLimelightNTDouble(limelightName, "tl"); + } + + /** + * Gets the capture latency. + * @param limelightName Name of the Limelight camera + * @return Capture latency in milliseconds + */ + public static double getLatency_Capture(String limelightName) { + return getLimelightNTDouble(limelightName, "cl"); + } + + /** + * Gets the active pipeline index. + * @param limelightName Name of the Limelight camera + * @return Current pipeline index (0-9) + */ + public static double getCurrentPipelineIndex(String limelightName) { + return getLimelightNTDouble(limelightName, "getpipe"); + } + + /** + * Gets the current pipeline type. + * @param limelightName Name of the Limelight camera + * @return Pipeline type string (e.g. "retro", "apriltag", etc) + */ + public static String getCurrentPipelineType(String limelightName) { + return getLimelightNTString(limelightName, "getpipetype"); + } + + /** + * Gets the full JSON results dump. + * @param limelightName Name of the Limelight camera + * @return JSON string containing all current results + */ + public static String getJSONDump(String limelightName) { + return getLimelightNTString(limelightName, "json"); + } + + /** + * Switch to getBotPose + * + * @param limelightName + * @return + */ + @Deprecated + public static double[] getBotpose(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "botpose"); + } + + /** + * Switch to getBotPose_wpiRed + * + * @param limelightName + * @return + */ + @Deprecated + public static double[] getBotpose_wpiRed(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "botpose_wpired"); + } + + /** + * Switch to getBotPose_wpiBlue + * + * @param limelightName + * @return + */ + @Deprecated + public static double[] getBotpose_wpiBlue(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "botpose_wpiblue"); + } + + public static double[] getBotPose(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "botpose"); + } + + public static double[] getBotPose_wpiRed(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "botpose_wpired"); + } + + public static double[] getBotPose_wpiBlue(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "botpose_wpiblue"); + } + + public static double[] getBotPose_TargetSpace(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "botpose_targetspace"); + } + + public static double[] getCameraPose_TargetSpace(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "camerapose_targetspace"); + } + + public static double[] getTargetPose_CameraSpace(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "targetpose_cameraspace"); + } + + public static double[] getTargetPose_RobotSpace(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "targetpose_robotspace"); + } + + public static double[] getTargetColor(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "tc"); + } + + public static double getFiducialID(String limelightName) { + return getLimelightNTDouble(limelightName, "tid"); + } + + public static String getNeuralClassID(String limelightName) { + return getLimelightNTString(limelightName, "tclass"); + } + + public static String[] getRawBarcodeData(String limelightName) { + return getLimelightNTStringArray(limelightName, "rawbarcodes"); + } + + ///// + ///// + + public static Pose3d getBotPose3d(String limelightName) { + double[] poseArray = getLimelightNTDoubleArray(limelightName, "botpose"); + return toPose3D(poseArray); + } + + /** + * (Not Recommended) Gets the robot's 3D pose in the WPILib Red Alliance Coordinate System. + * @param limelightName Name/identifier of the Limelight + * @return Pose3d object representing the robot's position and orientation in Red Alliance field space + */ + public static Pose3d getBotPose3d_wpiRed(String limelightName) { + double[] poseArray = getLimelightNTDoubleArray(limelightName, "botpose_wpired"); + return toPose3D(poseArray); + } + + /** + * (Recommended) Gets the robot's 3D pose in the WPILib Blue Alliance Coordinate System. + * @param limelightName Name/identifier of the Limelight + * @return Pose3d object representing the robot's position and orientation in Blue Alliance field space + */ + public static Pose3d getBotPose3d_wpiBlue(String limelightName) { + double[] poseArray = getLimelightNTDoubleArray(limelightName, "botpose_wpiblue"); + return toPose3D(poseArray); + } + + /** + * Gets the robot's 3D pose with respect to the currently tracked target's coordinate system. + * @param limelightName Name/identifier of the Limelight + * @return Pose3d object representing the robot's position and orientation relative to the target + */ + public static Pose3d getBotPose3d_TargetSpace(String limelightName) { + double[] poseArray = getLimelightNTDoubleArray(limelightName, "botpose_targetspace"); + return toPose3D(poseArray); + } + + /** + * Gets the camera's 3D pose with respect to the currently tracked target's coordinate system. + * @param limelightName Name/identifier of the Limelight + * @return Pose3d object representing the camera's position and orientation relative to the target + */ + public static Pose3d getCameraPose3d_TargetSpace(String limelightName) { + double[] poseArray = getLimelightNTDoubleArray(limelightName, "camerapose_targetspace"); + return toPose3D(poseArray); + } + + /** + * Gets the target's 3D pose with respect to the camera's coordinate system. + * @param limelightName Name/identifier of the Limelight + * @return Pose3d object representing the target's position and orientation relative to the camera + */ + public static Pose3d getTargetPose3d_CameraSpace(String limelightName) { + double[] poseArray = getLimelightNTDoubleArray(limelightName, "targetpose_cameraspace"); + return toPose3D(poseArray); + } + + /** + * Gets the target's 3D pose with respect to the robot's coordinate system. + * @param limelightName Name/identifier of the Limelight + * @return Pose3d object representing the target's position and orientation relative to the robot + */ + public static Pose3d getTargetPose3d_RobotSpace(String limelightName) { + double[] poseArray = getLimelightNTDoubleArray(limelightName, "targetpose_robotspace"); + return toPose3D(poseArray); + } + + /** + * Gets the camera's 3D pose with respect to the robot's coordinate system. + * @param limelightName Name/identifier of the Limelight + * @return Pose3d object representing the camera's position and orientation relative to the robot + */ + public static Pose3d getCameraPose3d_RobotSpace(String limelightName) { + double[] poseArray = getLimelightNTDoubleArray(limelightName, "camerapose_robotspace"); + return toPose3D(poseArray); + } + + /** + * Gets the Pose2d for easy use with Odometry vision pose estimator + * (addVisionMeasurement) + * + * @param limelightName + * @return + */ + public static Pose2d getBotPose2d_wpiBlue(String limelightName) { + + double[] result = getBotPose_wpiBlue(limelightName); + return toPose2D(result); + } + + /** + * Gets the MegaTag1 Pose2d and timestamp for use with WPILib pose estimator (addVisionMeasurement) in the WPILib Blue alliance coordinate system. + * + * @param limelightName + * @return + */ + public static PoseEstimate getBotPoseEstimate_wpiBlue(String limelightName) { + return getBotPoseEstimate(limelightName, "botpose_wpiblue", false); + } + + /** + * Gets the MegaTag2 Pose2d and timestamp for use with WPILib pose estimator (addVisionMeasurement) in the WPILib Blue alliance coordinate system. + * Make sure you are calling setRobotOrientation() before calling this method. + * + * @param limelightName + * @return + */ + public static PoseEstimate getBotPoseEstimate_wpiBlue_MegaTag2(String limelightName) { + return getBotPoseEstimate(limelightName, "botpose_orb_wpiblue", true); + } + + /** + * Gets the Pose2d for easy use with Odometry vision pose estimator + * (addVisionMeasurement) + * + * @param limelightName + * @return + */ + public static Pose2d getBotPose2d_wpiRed(String limelightName) { + + double[] result = getBotPose_wpiRed(limelightName); + return toPose2D(result); + + } + + /** + * Gets the Pose2d and timestamp for use with WPILib pose estimator (addVisionMeasurement) when you are on the RED + * alliance + * @param limelightName + * @return + */ + public static PoseEstimate getBotPoseEstimate_wpiRed(String limelightName) { + return getBotPoseEstimate(limelightName, "botpose_wpired", false); + } + + /** + * Gets the Pose2d and timestamp for use with WPILib pose estimator (addVisionMeasurement) when you are on the RED + * alliance + * @param limelightName + * @return + */ + public static PoseEstimate getBotPoseEstimate_wpiRed_MegaTag2(String limelightName) { + return getBotPoseEstimate(limelightName, "botpose_orb_wpired", true); + } + + /** + * Gets the Pose2d for easy use with Odometry vision pose estimator + * (addVisionMeasurement) + * + * @param limelightName + * @return + */ + public static Pose2d getBotPose2d(String limelightName) { + + double[] result = getBotPose(limelightName); + return toPose2D(result); + + } + + /** + * Gets the current IMU data from NetworkTables. + * IMU data is formatted as [robotYaw, Roll, Pitch, Yaw, gyroX, gyroY, gyroZ, accelX, accelY, accelZ]. + * Returns all zeros if data is invalid or unavailable. + * + * @param limelightName Name/identifier of the Limelight + * @return IMUData object containing all current IMU data + */ + public static IMUData getIMUData(String limelightName) { + double[] imuData = getLimelightNTDoubleArray(limelightName, "imu"); + if (imuData == null || imuData.length < 10) { + return new IMUData(); // Returns object with all zeros + } + return new IMUData(imuData); + } + + ///// + ///// + + public static void setPipelineIndex(String limelightName, int pipelineIndex) { + setLimelightNTDouble(limelightName, "pipeline", pipelineIndex); + } + + + public static void setPriorityTagID(String limelightName, int ID) { + setLimelightNTDouble(limelightName, "priorityid", ID); + } + + /** + * Sets LED mode to be controlled by the current pipeline. + * @param limelightName Name of the Limelight camera + */ + public static void setLEDMode_PipelineControl(String limelightName) { + setLimelightNTDouble(limelightName, "ledMode", 0); + } + + public static void setLEDMode_ForceOff(String limelightName) { + setLimelightNTDouble(limelightName, "ledMode", 1); + } + + public static void setLEDMode_ForceBlink(String limelightName) { + setLimelightNTDouble(limelightName, "ledMode", 2); + } + + public static void setLEDMode_ForceOn(String limelightName) { + setLimelightNTDouble(limelightName, "ledMode", 3); + } + + /** + * Enables standard side-by-side stream mode. + * @param limelightName Name of the Limelight camera + */ + public static void setStreamMode_Standard(String limelightName) { + setLimelightNTDouble(limelightName, "stream", 0); + } + + /** + * Enables Picture-in-Picture mode with secondary stream in the corner. + * @param limelightName Name of the Limelight camera + */ + public static void setStreamMode_PiPMain(String limelightName) { + setLimelightNTDouble(limelightName, "stream", 1); + } + + /** + * Enables Picture-in-Picture mode with primary stream in the corner. + * @param limelightName Name of the Limelight camera + */ + public static void setStreamMode_PiPSecondary(String limelightName) { + setLimelightNTDouble(limelightName, "stream", 2); + } + + + /** + * Sets the crop window for the camera. The crop window in the UI must be completely open. + * @param limelightName Name of the Limelight camera + * @param cropXMin Minimum X value (-1 to 1) + * @param cropXMax Maximum X value (-1 to 1) + * @param cropYMin Minimum Y value (-1 to 1) + * @param cropYMax Maximum Y value (-1 to 1) + */ + public static void setCropWindow(String limelightName, double cropXMin, double cropXMax, double cropYMin, double cropYMax) { + double[] entries = new double[4]; + entries[0] = cropXMin; + entries[1] = cropXMax; + entries[2] = cropYMin; + entries[3] = cropYMax; + setLimelightNTDoubleArray(limelightName, "crop", entries); + } + + /** + * Sets 3D offset point for easy 3D targeting. + */ + public static void setFiducial3DOffset(String limelightName, double offsetX, double offsetY, double offsetZ) { + double[] entries = new double[3]; + entries[0] = offsetX; + entries[1] = offsetY; + entries[2] = offsetZ; + setLimelightNTDoubleArray(limelightName, "fiducial_offset_set", entries); + } + + /** + * Sets robot orientation values used by MegaTag2 localization algorithm. + * + * @param limelightName Name/identifier of the Limelight + * @param yaw Robot yaw in degrees. 0 = robot facing red alliance wall in FRC + * @param yawRate (Unnecessary) Angular velocity of robot yaw in degrees per second + * @param pitch (Unnecessary) Robot pitch in degrees + * @param pitchRate (Unnecessary) Angular velocity of robot pitch in degrees per second + * @param roll (Unnecessary) Robot roll in degrees + * @param rollRate (Unnecessary) Angular velocity of robot roll in degrees per second + */ + public static void SetRobotOrientation(String limelightName, double yaw, double yawRate, + double pitch, double pitchRate, + double roll, double rollRate) { + SetRobotOrientation_INTERNAL(limelightName, yaw, yawRate, pitch, pitchRate, roll, rollRate, true); + } + + public static void SetRobotOrientation_NoFlush(String limelightName, double yaw, double yawRate, + double pitch, double pitchRate, + double roll, double rollRate) { + SetRobotOrientation_INTERNAL(limelightName, yaw, yawRate, pitch, pitchRate, roll, rollRate, false); + } + + private static void SetRobotOrientation_INTERNAL(String limelightName, double yaw, double yawRate, + double pitch, double pitchRate, + double roll, double rollRate, boolean flush) { + + double[] entries = new double[6]; + entries[0] = yaw; + entries[1] = yawRate; + entries[2] = pitch; + entries[3] = pitchRate; + entries[4] = roll; + entries[5] = rollRate; + setLimelightNTDoubleArray(limelightName, "robot_orientation_set", entries); + if(flush) + { + Flush(); + } + } + + /** + * Configures the IMU mode for MegaTag2 Localization + * + * @param limelightName Name/identifier of the Limelight + * @param mode IMU mode. + */ + public static void SetIMUMode(String limelightName, int mode) { + setLimelightNTDouble(limelightName, "imumode_set", mode); + } + + /** + * Configures the complementary filter alpha value for IMU Assist Modes (Modes 3 and 4) + * + * @param limelightName Name/identifier of the Limelight + * @param alpha Defaults to .001. Higher values will cause the internal IMU to converge onto the assist source more rapidly. + */ + public static void SetIMUAssistAlpha(String limelightName, double alpha) { + setLimelightNTDouble(limelightName, "imuassistalpha_set", alpha); + } + + + /** + * Configures the throttle value. Set to 100-200 while disabled to reduce thermal output/temperature. + * + * @param limelightName Name/identifier of the Limelight + * @param throttle Defaults to 0. Your Limelgiht will process one frame after skipping frames. + */ + public static void SetThrottle(String limelightName, int throttle) { + setLimelightNTDouble(limelightName, "throttle_set", throttle); + } + + /** + * Sets the 3D point-of-interest offset for the current fiducial pipeline. + * https://docs.limelightvision.io/docs/docs-limelight/pipeline-apriltag/apriltag-3d#point-of-interest-tracking + * + * @param limelightName Name/identifier of the Limelight + * @param x X offset in meters + * @param y Y offset in meters + * @param z Z offset in meters + */ + public static void SetFidcuial3DOffset(String limelightName, double x, double y, + double z) { + + double[] entries = new double[3]; + entries[0] = x; + entries[1] = y; + entries[2] = z; + setLimelightNTDoubleArray(limelightName, "fiducial_offset_set", entries); + } + + /** + * Overrides the valid AprilTag IDs that will be used for localization. + * Tags not in this list will be ignored for robot pose estimation. + * + * @param limelightName Name/identifier of the Limelight + * @param validIDs Array of valid AprilTag IDs to track + */ + public static void SetFiducialIDFiltersOverride(String limelightName, int[] validIDs) { + double[] validIDsDouble = new double[validIDs.length]; + for (int i = 0; i < validIDs.length; i++) { + validIDsDouble[i] = validIDs[i]; + } + setLimelightNTDoubleArray(limelightName, "fiducial_id_filters_set", validIDsDouble); + } + + /** + * Sets the downscaling factor for AprilTag detection. + * Increasing downscale can improve performance at the cost of potentially reduced detection range. + * + * @param limelightName Name/identifier of the Limelight + * @param downscale Downscale factor. Valid values: 1.0 (no downscale), 1.5, 2.0, 3.0, 4.0. Set to 0 for pipeline control. + */ + public static void SetFiducialDownscalingOverride(String limelightName, float downscale) + { + int d = 0; // pipeline + if (downscale == 1.0) + { + d = 1; + } + if (downscale == 1.5) + { + d = 2; + } + if (downscale == 2) + { + d = 3; + } + if (downscale == 3) + { + d = 4; + } + if (downscale == 4) + { + d = 5; + } + setLimelightNTDouble(limelightName, "fiducial_downscale_set", d); + } + + /** + * Sets the camera pose relative to the robot. + * @param limelightName Name of the Limelight camera + * @param forward Forward offset in meters + * @param side Side offset in meters + * @param up Up offset in meters + * @param roll Roll angle in degrees + * @param pitch Pitch angle in degrees + * @param yaw Yaw angle in degrees + */ + public static void setCameraPose_RobotSpace(String limelightName, double forward, double side, double up, double roll, double pitch, double yaw) { + double[] entries = new double[6]; + entries[0] = forward; + entries[1] = side; + entries[2] = up; + entries[3] = roll; + entries[4] = pitch; + entries[5] = yaw; + setLimelightNTDoubleArray(limelightName, "camerapose_robotspace_set", entries); + } + + ///// + ///// + + public static void setPythonScriptData(String limelightName, double[] outgoingPythonData) { + setLimelightNTDoubleArray(limelightName, "llrobot", outgoingPythonData); + } + + public static double[] getPythonScriptData(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "llpython"); + } + + ///// + ///// + + /** + * Asynchronously take snapshot. + */ + public static CompletableFuture takeSnapshot(String tableName, String snapshotName) { + return CompletableFuture.supplyAsync(() -> { + return SYNCH_TAKESNAPSHOT(tableName, snapshotName); + }); + } + + private static boolean SYNCH_TAKESNAPSHOT(String tableName, String snapshotName) { + URL url = getLimelightURLString(tableName, "capturesnapshot"); + try { + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + if (snapshotName != null && !"".equals(snapshotName)) { + connection.setRequestProperty("snapname", snapshotName); + } + + int responseCode = connection.getResponseCode(); + if (responseCode == 200) { + return true; + } else { + System.err.println("Bad LL Request"); + } + } catch (IOException e) { + System.err.println(e.getMessage()); + } + return false; + } + + /** + * Gets the latest JSON results output and returns a LimelightResults object. + * @param limelightName Name of the Limelight camera + * @return LimelightResults object containing all current target data + */ + public static LimelightResults getLatestResults(String limelightName) { + + long start = System.nanoTime(); + LimelightHelpers.LimelightResults results = new LimelightHelpers.LimelightResults(); + if (mapper == null) { + mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } + + try { + results = mapper.readValue(getJSONDump(limelightName), LimelightResults.class); + } catch (JsonProcessingException e) { + results.error = "lljson error: " + e.getMessage(); + } + + long end = System.nanoTime(); + double millis = (end - start) * .000001; + results.latency_jsonParse = millis; + if (profileJSON) { + System.out.printf("lljson: %.2f\r\n", millis); + } + + return results; + } +} \ No newline at end of file diff --git a/src/main/java/frc/robot/subsystems/PuncherSubsystem.java b/src/main/java/frc/robot/subsystems/PuncherSubsystem.java new file mode 100644 index 0000000..8c046d5 --- /dev/null +++ b/src/main/java/frc/robot/subsystems/PuncherSubsystem.java @@ -0,0 +1,216 @@ +package frc.robot.subsystems; + +import java.util.function.DoubleSupplier; + +import com.ctre.phoenix.motorcontrol.NeutralMode; +import com.ctre.phoenix.motorcontrol.TalonSRXControlMode; +import com.ctre.phoenix.motorcontrol.can.TalonSRX; +import com.ctre.phoenix6.configs.CurrentLimitsConfigs; +import com.ctre.phoenix6.configs.MotorOutputConfigs; +import com.ctre.phoenix6.configs.Slot0Configs; +import com.ctre.phoenix6.configs.SoftwareLimitSwitchConfigs; +import com.ctre.phoenix6.configs.TalonFXConfiguration; +import com.ctre.phoenix6.configs.TalonFXConfigurator; +import com.ctre.phoenix6.controls.DutyCycleOut; +import com.ctre.phoenix6.controls.Follower; +import com.ctre.phoenix6.controls.PositionDutyCycle; +import com.ctre.phoenix6.hardware.TalonFX; +import com.ctre.phoenix6.signals.NeutralModeValue; + +import edu.wpi.first.networktables.GenericEntry; +import edu.wpi.first.wpilibj.DigitalInput; +import edu.wpi.first.wpilibj.Encoder; +import edu.wpi.first.wpilibj.shuffleboard.BuiltInWidgets; +import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.Commands; +import edu.wpi.first.wpilibj2.command.InstantCommand; +import edu.wpi.first.wpilibj2.command.SubsystemBase; +import frc.robot.Constants; + +public class PuncherSubsystem extends SubsystemBase { + private final TalonFX puncherLeftMotor; + private final TalonFX puncherRightMotor; + private final Follower follower; + + private final TalonSRX puncherReleaseMotor; + private final Encoder puncherReleaseFeedback; + + private final DutyCycleOut percentOutCycle = new DutyCycleOut(0); + private final PositionDutyCycle positionCycle = new PositionDutyCycle(0); + private boolean isPuncherReady = false; + + private GenericEntry setpointValue; + private GenericEntry releaseTimeInValue; + private GenericEntry releaseTimeOutValue; + private GenericEntry releaseDutyCycleValue; + private GenericEntry tightenDutyCycleValue; + private GenericEntry encoderSetpointValue; + + public PuncherSubsystem() { + puncherLeftMotor = new TalonFX(Constants.PuncherConstants.LEFT_MOTOR_CAN_ID); + puncherRightMotor = new TalonFX(Constants.PuncherConstants.RIGHT_MOTOR_CAN_ID); + follower = new Follower(Constants.PuncherConstants.LEFT_MOTOR_CAN_ID, false); + puncherReleaseMotor = new TalonSRX(Constants.PuncherConstants.RELEASE_MOTOR_CAN_ID); + puncherReleaseFeedback = new Encoder(Constants.PuncherConstants.ENCODER_DIO_PORT_B, Constants.PuncherConstants.ENCODER_DIO_PORT_A); + + puncherReleaseMotor.setNeutralMode(NeutralMode.Brake); + + puncherLeftMotor.setPosition(0); + puncherRightMotor.setPosition(0); + + puncherLeftMotor.getConfigurator().apply(new TalonFXConfiguration()); + puncherRightMotor.getConfigurator().apply(new TalonFXConfiguration()); + + TalonFXConfigurator masterConfig = puncherLeftMotor.getConfigurator(); + TalonFXConfigurator slaveConfig = puncherRightMotor.getConfigurator(); + + Slot0Configs positionPIDConfigs = new Slot0Configs(); + positionPIDConfigs.kP = 0.2; + positionPIDConfigs.kI = 0.005; + positionPIDConfigs.kD = 0; + positionPIDConfigs.kA = 0; + masterConfig.apply(positionPIDConfigs); + slaveConfig.apply(positionPIDConfigs); + + MotorOutputConfigs outputConfigs = new MotorOutputConfigs(); + outputConfigs.PeakForwardDutyCycle = 1; + outputConfigs.PeakReverseDutyCycle = -1; + outputConfigs.withNeutralMode(NeutralModeValue.Coast); + //outputConfigs.withInverted(InvertedValue.Clockwise_Positive); + masterConfig.apply(outputConfigs); + slaveConfig.apply(outputConfigs); + + SoftwareLimitSwitchConfigs limitSwitchConfigs = new SoftwareLimitSwitchConfigs(); + limitSwitchConfigs.ForwardSoftLimitEnable = false; + limitSwitchConfigs.ReverseSoftLimitEnable = false; + limitSwitchConfigs.ForwardSoftLimitThreshold = 0; + limitSwitchConfigs.ReverseSoftLimitThreshold = 0; + masterConfig.apply(limitSwitchConfigs); + slaveConfig.apply(limitSwitchConfigs); + + CurrentLimitsConfigs currentLimitsConfigs = new CurrentLimitsConfigs(); + currentLimitsConfigs.StatorCurrentLimitEnable = false; + currentLimitsConfigs.SupplyCurrentLimitEnable = true; + currentLimitsConfigs.SupplyCurrentLimit = 35; + currentLimitsConfigs.SupplyCurrentLowerLimit = 30; + currentLimitsConfigs.SupplyCurrentLowerTime = 1; + masterConfig.apply(currentLimitsConfigs); + slaveConfig.apply(currentLimitsConfigs); + + puncherReleaseFeedback.reset(); + + if(Constants.DEV_MODE) { + setpointValue = Shuffleboard.getTab("Puncher Subsystem").add("Setpoint", 45) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + + releaseTimeInValue = Shuffleboard.getTab("Puncher Subsystem").add("Release: Timer", 0.3) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + + releaseTimeOutValue = Shuffleboard.getTab("Puncher Subsystem").add("Tighten: Timer", 0.3) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + + releaseDutyCycleValue = Shuffleboard.getTab("Puncher Subsystem").add("Release: DutyCycleOut", 0.3) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + + tightenDutyCycleValue = Shuffleboard.getTab("Puncher Subsystem").add("Tighten: DutyCycleOut", 0.31) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + + encoderSetpointValue = Shuffleboard.getTab("Puncher Subsystem").add("Release: Setpoint", 500) + .withWidget(BuiltInWidgets.kTextView).getEntry(); + } + } + + public boolean isPuncherReady() { + return isPuncherReady; + } + + public void setIsPuncherReady(boolean isPuncherReady) { + this.isPuncherReady = isPuncherReady; + } + + public double getPosition() { + return puncherLeftMotor.getPosition().getValueAsDouble(); + } + + public void resetPosition(){ + puncherLeftMotor.setPosition(0); + } + + public void goToPosition(double position) { + puncherLeftMotor.setControl(positionCycle.withPosition(position)); + puncherRightMotor.setControl(follower); + } + + public void percentOut(double speed) { + puncherLeftMotor.setControl(percentOutCycle.withOutput(speed)); + puncherRightMotor.setControl(follower); + } + + public void stop() { + puncherLeftMotor.stopMotor(); + puncherRightMotor.stopMotor(); + } + + public void setRelease(double speed) { + puncherReleaseMotor.set(TalonSRXControlMode.PercentOutput, speed); + } + + public void stopRelease() { + puncherReleaseMotor.set(TalonSRXControlMode.PercentOutput, 0); + } + + public void resetEncoders() { + puncherLeftMotor.setPosition(0); + puncherRightMotor.setPosition(0); + puncherReleaseFeedback.reset(); + } + + public Command buildUpCommand(DoubleSupplier position) { + return Commands.startEnd(() -> this.goToPosition(position.getAsDouble()), () -> {this.goToPosition(0); + this.setIsPuncherReady(true);}, this); //ADICIONAR UNTIL PARA POSICAO ESPECIFICA E TESTAR + } + + public Command releaseCommand(DoubleSupplier speed1, DoubleSupplier speed2) { + return Commands.startEnd(() -> this.setRelease(-speed1.getAsDouble()), this::stopRelease, this) + .until(() -> puncherReleaseFeedback.get() == 500).andThen + (Commands.startEnd(() -> this.setRelease(speed2.getAsDouble()), () -> {this.stopRelease(); + this.setIsPuncherReady(false);}, this) + .until(() -> puncherReleaseFeedback.get() == 0)); + } + + public Command testPrintCommand() { + return new InstantCommand(() -> System.out.println(setpointValue.getDouble(40)), this).ignoringDisable(true); + } + + public Command testBuildUpCommand() { + return Commands.startEnd(() -> this.goToPosition(setpointValue.getDouble(45)), () -> {this.goToPosition(0); + this.setIsPuncherReady(true);}, this).until(() -> puncherLeftMotor.getPosition().getValueAsDouble() > 20); + } + + public Command testReleaseCommand() { + return Commands.startEnd(() -> this.setRelease(-0.3), this::stopRelease, this) + .until(() -> puncherReleaseFeedback.get() > 440).andThen + (Commands.startEnd(() -> this.setRelease(0.3), () -> {this.stopRelease(); + this.setIsPuncherReady(false);}, this) + .until(() -> puncherReleaseFeedback.get() < 10)); + } + + public void resetState() { + this.setIsPuncherReady(false); + } + + public void debug() { + SmartDashboard.putNumber("Puncher Subsystem/Release/Feedback", puncherReleaseFeedback.get()); + SmartDashboard.putBoolean("Puncher Subsystem/State", isPuncherReady()); + SmartDashboard.putNumber("Puncher Subsystem/Motor", puncherLeftMotor.getPosition().getValueAsDouble()); + } + + @Override + public void periodic() { + if(Constants.DEV_MODE) { + this.debug(); + } + } +} \ No newline at end of file diff --git a/src/main/java/frc/robot/subsystems/Shooter.java b/src/main/java/frc/robot/subsystems/Shooter.java deleted file mode 100644 index d490556..0000000 --- a/src/main/java/frc/robot/subsystems/Shooter.java +++ /dev/null @@ -1,21 +0,0 @@ -package frc.robot.subsystems; - -import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; -import edu.wpi.first.wpilibj2.command.SubsystemBase; -import frc.robot.subsystems.swervedrive.Vision; - -public class Shooter extends SubsystemBase { - Vision vision; - - public Shooter(Vision vision){ - this.vision = vision; - } - - @Override - public void periodic(){ - SmartDashboard.putNumber("Distance From Apriltag", vision.getDistanceFromAprilTag(1)); - SmartDashboard.putNumber("Apriltag X", vision.getXApriltag(1)); - SmartDashboard.putNumber("Apriltag Y", vision.getYApriltag(1)); - - } -} diff --git a/src/main/java/frc/robot/subsystems/swervedrive/SwerveSubsystem.java b/src/main/java/frc/robot/subsystems/swervedrive/SwerveSubsystem.java index 851a06d..02148dc 100644 --- a/src/main/java/frc/robot/subsystems/swervedrive/SwerveSubsystem.java +++ b/src/main/java/frc/robot/subsystems/swervedrive/SwerveSubsystem.java @@ -21,7 +21,6 @@ import edu.wpi.first.apriltag.AprilTagFields; import edu.wpi.first.math.controller.SimpleMotorFeedforward; import edu.wpi.first.math.geometry.Pose2d; -import edu.wpi.first.math.geometry.Pose3d; import edu.wpi.first.math.geometry.Rotation2d; import edu.wpi.first.math.geometry.Translation2d; import edu.wpi.first.math.kinematics.ChassisSpeeds; @@ -29,7 +28,6 @@ import edu.wpi.first.math.trajectory.Trajectory; import edu.wpi.first.math.util.Units; import edu.wpi.first.wpilibj.DriverStation; -import edu.wpi.first.wpilibj.DriverStation.Alliance; import edu.wpi.first.wpilibj.Timer; import edu.wpi.first.wpilibj2.command.Command; import edu.wpi.first.wpilibj2.command.Commands; @@ -104,7 +102,7 @@ public SwerveSubsystem(File directory) 0.1); //Correct for skew that gets worse as angular velocity increases. Start with a coefficient of 0.1. swerveDrive.setModuleEncoderAutoSynchronize(false, 1); // Enable if you want to resynchronize your absolute encoders and motor encoders periodically when they are not moving. -// swerveDrive.pushOffsetsToEncoders(); // Set the absolute encoder to be used over the internal encoder and push the offsets onto it. Throws warning if not possible + //swerveDrive.pushOffsetsToEncoders(); // Set the absolute encoder to be used over the internal encoder and push the offsets onto it. Throws warning if not possible if (visionDriveTest) { setupPhotonVision(); diff --git a/src/main/java/frc/robot/subsystems/swervetank/Drivetrain.java b/src/main/java/frc/robot/subsystems/swervetank/Drivetrain.java new file mode 100644 index 0000000..c408677 --- /dev/null +++ b/src/main/java/frc/robot/subsystems/swervetank/Drivetrain.java @@ -0,0 +1,138 @@ +package frc.robot.subsystems.swervetank; + +import java.nio.file.ClosedFileSystemException; +import java.util.function.DoubleSupplier; + +import com.revrobotics.spark.ClosedLoopSlot; +import com.revrobotics.spark.SparkClosedLoopController; +import com.revrobotics.spark.SparkMax; +import com.revrobotics.spark.SparkBase.ControlType; +import com.revrobotics.spark.SparkBase.PersistMode; +import com.revrobotics.spark.SparkBase.ResetMode; +import com.revrobotics.spark.SparkLowLevel.MotorType; +import com.revrobotics.spark.config.SparkMaxConfig; +import com.revrobotics.spark.config.ClosedLoopConfig.FeedbackSensor; +import com.revrobotics.spark.config.SparkBaseConfig.IdleMode; + +import edu.wpi.first.wpilibj.drive.DifferentialDrive; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.SubsystemBase; +import edu.wpi.first.wpilibj2.command.button.CommandXboxController; + +public class Drivetrain extends SubsystemBase { + private final DifferentialDrive differentialDrive; + + private final SparkMax leftFrontDrive; + private final SparkMax leftBackDrive; + private final SparkMax rightFrontDrive; + private final SparkMax rightBackDrive; + + private final SparkMax leftFrontAngle; + private final SparkMax leftBackAngle; + private final SparkMax rightFrontAngle; + private final SparkMax rightBackAngle; + + private final SparkClosedLoopController leftFrontAngleClosedLoopController; + private final SparkClosedLoopController leftBackAngleClosedLoopController; + private final SparkClosedLoopController rightFrontAngleClosedLoopController; + private final SparkClosedLoopController rightBackAngleClosedLoopController; + + private final SparkMaxConfig globalDriveConfig; + private final SparkMaxConfig globalAngleConfig; + + private final SparkMaxConfig leftFollowerConfig; + private final SparkMaxConfig rightFollowerConfig; + + + public Drivetrain() { + leftFrontDrive = new SparkMax(1, MotorType.kBrushless); + leftBackDrive = new SparkMax(7, MotorType.kBrushless); + rightFrontDrive = new SparkMax(3, MotorType.kBrushless); + rightBackDrive = new SparkMax(5, MotorType.kBrushless); + + leftFrontAngle = new SparkMax(4, MotorType.kBrushless); + leftBackAngle = new SparkMax(9, MotorType.kBrushless); + rightFrontAngle = new SparkMax(2, MotorType.kBrushless); + rightBackAngle = new SparkMax(6, MotorType.kBrushless); + + leftFrontAngleClosedLoopController = leftFrontAngle.getClosedLoopController(); + leftBackAngleClosedLoopController = leftBackAngle.getClosedLoopController(); + rightFrontAngleClosedLoopController = rightFrontAngle.getClosedLoopController(); + rightBackAngleClosedLoopController = rightBackAngle.getClosedLoopController(); + + globalDriveConfig = new SparkMaxConfig(); + globalAngleConfig = new SparkMaxConfig(); + + leftFollowerConfig = new SparkMaxConfig(); + rightFollowerConfig = new SparkMaxConfig(); + + globalDriveConfig + .smartCurrentLimit(50) + .idleMode(IdleMode.kBrake); + + globalAngleConfig + .smartCurrentLimit(50) + .idleMode(IdleMode.kBrake); + + globalAngleConfig.encoder + .positionConversionFactor(1) + .velocityConversionFactor(1); + + globalAngleConfig.closedLoop + .feedbackSensor(FeedbackSensor.kPrimaryEncoder) + .p(0.1) + .i(0) + .d(0) + .outputRange(-1, 1); + + leftFollowerConfig + .apply(globalDriveConfig) + .follow(leftFrontDrive); + + rightFollowerConfig + .apply(globalDriveConfig) + .follow(rightFrontDrive); + + leftFrontDrive.configure(globalDriveConfig, ResetMode.kResetSafeParameters, PersistMode.kPersistParameters); + leftBackDrive.configure(leftFollowerConfig, ResetMode.kResetSafeParameters, PersistMode.kPersistParameters); + rightFrontDrive.configure(globalDriveConfig, ResetMode.kResetSafeParameters, PersistMode.kPersistParameters); + rightBackDrive.configure(rightFollowerConfig, ResetMode.kResetSafeParameters, PersistMode.kPersistParameters); + + leftFrontAngle.configure(globalAngleConfig, ResetMode.kResetSafeParameters, PersistMode.kPersistParameters); + leftBackAngle.configure(globalAngleConfig, ResetMode.kResetSafeParameters, PersistMode.kPersistParameters); + rightFrontAngle.configure(globalAngleConfig, ResetMode.kResetSafeParameters, PersistMode.kPersistParameters); + rightBackAngle.configure(globalAngleConfig, ResetMode.kResetSafeParameters, PersistMode.kPersistParameters); + + differentialDrive = new DifferentialDrive(leftFrontDrive::set, rightFrontDrive::set); + } + + public Command drive(DoubleSupplier leftSpeed, DoubleSupplier rightSpeed) { + return this.run(() -> differentialDrive.arcadeDrive(-leftSpeed.getAsDouble(), -rightSpeed.getAsDouble())); + } + + public void setMotorBrake(boolean isBrake) { + + } + + public void zeroGyro() { + + } + + public Command autonomousCommand() { + return this.runEnd(() -> differentialDrive.tankDrive(-0.8, -0.8), differentialDrive::stopMotor).withTimeout(5); + } + + public void lockMotors() { + leftFrontAngleClosedLoopController.setReference(0, ControlType.kPosition, ClosedLoopSlot.kSlot0); + leftBackAngleClosedLoopController.setReference(0, ControlType.kPosition, ClosedLoopSlot.kSlot0); + rightFrontAngleClosedLoopController.setReference(0, ControlType.kPosition, ClosedLoopSlot.kSlot0); + rightBackAngleClosedLoopController.setReference(0, ControlType.kPosition, ClosedLoopSlot.kSlot0); + } + + @Override + public void periodic() { + SmartDashboard.putNumber("Tank/Position", leftFrontAngle.getEncoder().getPosition()); + lockMotors(); + } +} diff --git a/vendordeps/PathplannerLib-2025.2.6.json b/vendordeps/PathplannerLib-2025.2.6.json new file mode 100644 index 0000000..95ba203 --- /dev/null +++ b/vendordeps/PathplannerLib-2025.2.6.json @@ -0,0 +1,38 @@ +{ + "fileName": "PathplannerLib-2025.2.6.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" + ] + } + ] +} \ No newline at end of file diff --git a/vendordeps/PathplannerLib.json b/vendordeps/PathplannerLib.json deleted file mode 100644 index eef8f6e..0000000 --- a/vendordeps/PathplannerLib.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "fileName": "PathplannerLib.json", - "name": "PathplannerLib", - "version": "2025.2.1", - "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.1" - } - ], - "jniDependencies": [], - "cppDependencies": [ - { - "groupId": "com.pathplanner.lib", - "artifactId": "PathplannerLib-cpp", - "version": "2025.2.1", - "libName": "PathplannerLib", - "headerClassifier": "headers", - "sharedLibrary": false, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal", - "linuxathena", - "linuxarm32", - "linuxarm64" - ] - } - ] -} \ No newline at end of file diff --git a/vendordeps/Phoenix6-25.2.1.json b/vendordeps/Phoenix6-25.2.1.json deleted file mode 100644 index 04fa95a..0000000 --- a/vendordeps/Phoenix6-25.2.1.json +++ /dev/null @@ -1,419 +0,0 @@ -{ - "fileName": "Phoenix6-25.2.1.json", - "name": "CTRE-Phoenix (v6)", - "version": "25.2.1", - "frcYear": "2025", - "uuid": "e995de00-2c64-4df5-8831-c1441420ff19", - "mavenUrls": [ - "https://maven.ctr-electronics.com/release/" - ], - "jsonUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix6/latest/Phoenix6-frc2025-latest.json", - "conflictsWith": [ - { - "uuid": "e7900d8d-826f-4dca-a1ff-182f658e98af", - "errorMessage": "Users can not have both the replay and regular Phoenix 6 vendordeps in their robot program.", - "offlineFileName": "Phoenix6-replay-frc2025-latest.json" - } - ], - "javaDependencies": [ - { - "groupId": "com.ctre.phoenix6", - "artifactId": "wpiapi-java", - "version": "25.2.1" - } - ], - "jniDependencies": [ - { - "groupId": "com.ctre.phoenix6", - "artifactId": "api-cpp", - "version": "25.2.1", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "linuxathena" - ], - "simMode": "hwsim" - }, - { - "groupId": "com.ctre.phoenix6", - "artifactId": "tools", - "version": "25.2.1", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "linuxathena" - ], - "simMode": "hwsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "api-cpp-sim", - "version": "25.2.1", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "tools-sim", - "version": "25.2.1", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simTalonSRX", - "version": "25.2.1", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simVictorSPX", - "version": "25.2.1", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simPigeonIMU", - "version": "25.2.1", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simCANCoder", - "version": "25.2.1", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simProTalonFX", - "version": "25.2.1", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simProTalonFXS", - "version": "25.2.1", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simProCANcoder", - "version": "25.2.1", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simProPigeon2", - "version": "25.2.1", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simProCANrange", - "version": "25.2.1", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - } - ], - "cppDependencies": [ - { - "groupId": "com.ctre.phoenix6", - "artifactId": "wpiapi-cpp", - "version": "25.2.1", - "libName": "CTRE_Phoenix6_WPI", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "linuxathena" - ], - "simMode": "hwsim" - }, - { - "groupId": "com.ctre.phoenix6", - "artifactId": "tools", - "version": "25.2.1", - "libName": "CTRE_PhoenixTools", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "linuxathena" - ], - "simMode": "hwsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "wpiapi-cpp-sim", - "version": "25.2.1", - "libName": "CTRE_Phoenix6_WPISim", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "tools-sim", - "version": "25.2.1", - "libName": "CTRE_PhoenixTools_Sim", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simTalonSRX", - "version": "25.2.1", - "libName": "CTRE_SimTalonSRX", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simVictorSPX", - "version": "25.2.1", - "libName": "CTRE_SimVictorSPX", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simPigeonIMU", - "version": "25.2.1", - "libName": "CTRE_SimPigeonIMU", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simCANCoder", - "version": "25.2.1", - "libName": "CTRE_SimCANCoder", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simProTalonFX", - "version": "25.2.1", - "libName": "CTRE_SimProTalonFX", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simProTalonFXS", - "version": "25.2.1", - "libName": "CTRE_SimProTalonFXS", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simProCANcoder", - "version": "25.2.1", - "libName": "CTRE_SimProCANcoder", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simProPigeon2", - "version": "25.2.1", - "libName": "CTRE_SimProPigeon2", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simProCANrange", - "version": "25.2.1", - "libName": "CTRE_SimProCANrange", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - } - ] -} \ No newline at end of file diff --git a/vendordeps/Phoenix6-25.3.1.json b/vendordeps/Phoenix6-25.3.1.json new file mode 100644 index 0000000..a216d97 --- /dev/null +++ b/vendordeps/Phoenix6-25.3.1.json @@ -0,0 +1,449 @@ +{ + "fileName": "Phoenix6-25.3.1.json", + "name": "CTRE-Phoenix (v6)", + "version": "25.3.1", + "frcYear": "2025", + "uuid": "e995de00-2c64-4df5-8831-c1441420ff19", + "mavenUrls": [ + "https://maven.ctr-electronics.com/release/" + ], + "jsonUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix6/latest/Phoenix6-frc2025-latest.json", + "conflictsWith": [ + { + "uuid": "e7900d8d-826f-4dca-a1ff-182f658e98af", + "errorMessage": "Users can not have both the replay and regular Phoenix 6 vendordeps in their robot program.", + "offlineFileName": "Phoenix6-replay-frc2025-latest.json" + } + ], + "javaDependencies": [ + { + "groupId": "com.ctre.phoenix6", + "artifactId": "wpiapi-java", + "version": "25.3.1" + } + ], + "jniDependencies": [ + { + "groupId": "com.ctre.phoenix6", + "artifactId": "api-cpp", + "version": "25.3.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6", + "artifactId": "tools", + "version": "25.3.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "api-cpp-sim", + "version": "25.3.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "tools-sim", + "version": "25.3.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simTalonSRX", + "version": "25.3.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simVictorSPX", + "version": "25.3.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simPigeonIMU", + "version": "25.3.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simCANCoder", + "version": "25.3.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProTalonFX", + "version": "25.3.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProTalonFXS", + "version": "25.3.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANcoder", + "version": "25.3.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProPigeon2", + "version": "25.3.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANrange", + "version": "25.3.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANdi", + "version": "25.3.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + } + ], + "cppDependencies": [ + { + "groupId": "com.ctre.phoenix6", + "artifactId": "wpiapi-cpp", + "version": "25.3.1", + "libName": "CTRE_Phoenix6_WPI", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6", + "artifactId": "tools", + "version": "25.3.1", + "libName": "CTRE_PhoenixTools", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "wpiapi-cpp-sim", + "version": "25.3.1", + "libName": "CTRE_Phoenix6_WPISim", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "tools-sim", + "version": "25.3.1", + "libName": "CTRE_PhoenixTools_Sim", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simTalonSRX", + "version": "25.3.1", + "libName": "CTRE_SimTalonSRX", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simVictorSPX", + "version": "25.3.1", + "libName": "CTRE_SimVictorSPX", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simPigeonIMU", + "version": "25.3.1", + "libName": "CTRE_SimPigeonIMU", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simCANCoder", + "version": "25.3.1", + "libName": "CTRE_SimCANCoder", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProTalonFX", + "version": "25.3.1", + "libName": "CTRE_SimProTalonFX", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProTalonFXS", + "version": "25.3.1", + "libName": "CTRE_SimProTalonFXS", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANcoder", + "version": "25.3.1", + "libName": "CTRE_SimProCANcoder", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProPigeon2", + "version": "25.3.1", + "libName": "CTRE_SimProPigeon2", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANrange", + "version": "25.3.1", + "libName": "CTRE_SimProCANrange", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANdi", + "version": "25.3.1", + "libName": "CTRE_SimProCANdi", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + } + ] +} \ No newline at end of file diff --git a/vendordeps/REVLib.json b/vendordeps/REVLib.json index ac85012..ac62be8 100644 --- a/vendordeps/REVLib.json +++ b/vendordeps/REVLib.json @@ -1,71 +1,71 @@ { - "fileName": "REVLib.json", - "name": "REVLib", - "version": "2025.0.1", - "frcYear": "2025", - "uuid": "3f48eb8c-50fe-43a6-9cb7-44c86353c4cb", - "mavenUrls": [ - "https://maven.revrobotics.com/" - ], - "jsonUrl": "https://software-metadata.revrobotics.com/REVLib-2025.json", - "javaDependencies": [ - { - "groupId": "com.revrobotics.frc", - "artifactId": "REVLib-java", - "version": "2025.0.1" - } - ], - "jniDependencies": [ - { - "groupId": "com.revrobotics.frc", - "artifactId": "REVLib-driver", - "version": "2025.0.1", - "skipInvalidPlatforms": true, - "isJar": false, - "validPlatforms": [ - "windowsx86-64", - "linuxarm64", - "linuxx86-64", - "linuxathena", - "linuxarm32", - "osxuniversal" - ] - } - ], - "cppDependencies": [ - { - "groupId": "com.revrobotics.frc", - "artifactId": "REVLib-cpp", - "version": "2025.0.1", - "libName": "REVLib", - "headerClassifier": "headers", - "sharedLibrary": false, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxarm64", - "linuxx86-64", - "linuxathena", - "linuxarm32", - "osxuniversal" - ] - }, - { - "groupId": "com.revrobotics.frc", - "artifactId": "REVLib-driver", - "version": "2025.0.1", - "libName": "REVLibDriver", - "headerClassifier": "headers", - "sharedLibrary": false, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxarm64", - "linuxx86-64", - "linuxathena", - "linuxarm32", - "osxuniversal" - ] - } - ] + "fileName": "REVLib.json", + "name": "REVLib", + "version": "2025.0.3", + "frcYear": "2025", + "uuid": "3f48eb8c-50fe-43a6-9cb7-44c86353c4cb", + "mavenUrls": [ + "https://maven.revrobotics.com/" + ], + "jsonUrl": "https://software-metadata.revrobotics.com/REVLib-2025.json", + "javaDependencies": [ + { + "groupId": "com.revrobotics.frc", + "artifactId": "REVLib-java", + "version": "2025.0.3" + } + ], + "jniDependencies": [ + { + "groupId": "com.revrobotics.frc", + "artifactId": "REVLib-driver", + "version": "2025.0.3", + "skipInvalidPlatforms": true, + "isJar": false, + "validPlatforms": [ + "windowsx86-64", + "linuxarm64", + "linuxx86-64", + "linuxathena", + "linuxarm32", + "osxuniversal" + ] + } + ], + "cppDependencies": [ + { + "groupId": "com.revrobotics.frc", + "artifactId": "REVLib-cpp", + "version": "2025.0.3", + "libName": "REVLib", + "headerClassifier": "headers", + "sharedLibrary": false, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxarm64", + "linuxx86-64", + "linuxathena", + "linuxarm32", + "osxuniversal" + ] + }, + { + "groupId": "com.revrobotics.frc", + "artifactId": "REVLib-driver", + "version": "2025.0.3", + "libName": "REVLibDriver", + "headerClassifier": "headers", + "sharedLibrary": false, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxarm64", + "linuxx86-64", + "linuxathena", + "linuxarm32", + "osxuniversal" + ] + } + ] } \ No newline at end of file diff --git a/vendordeps/ReduxLib-2025.0.0.json b/vendordeps/ReduxLib-2025.0.0.json deleted file mode 100644 index 41303ed..0000000 --- a/vendordeps/ReduxLib-2025.0.0.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "fileName": "ReduxLib-2025.0.0.json", - "name": "ReduxLib", - "version": "2025.0.0", - "frcYear": "2025", - "uuid": "151ecca8-670b-4026-8160-cdd2679ef2bd", - "mavenUrls": [ - "https://maven.reduxrobotics.com/" - ], - "jsonUrl": "https://frcsdk.reduxrobotics.com/ReduxLib_2025.json", - "javaDependencies": [ - { - "groupId": "com.reduxrobotics.frc", - "artifactId": "ReduxLib-java", - "version": "2025.0.0" - } - ], - "jniDependencies": [ - { - "groupId": "com.reduxrobotics.frc", - "artifactId": "ReduxLib-driver", - "version": "2025.0.0", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "linuxathena", - "linuxx86-64", - "linuxarm32", - "linuxarm64", - "osxuniversal", - "windowsx86-64" - ] - } - ], - "cppDependencies": [ - { - "groupId": "com.reduxrobotics.frc", - "artifactId": "ReduxLib-cpp", - "version": "2025.0.0", - "libName": "ReduxLib", - "headerClassifier": "headers", - "sourcesClassifier": "sources", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "linuxathena", - "linuxx86-64", - "linuxarm32", - "linuxarm64", - "osxuniversal", - "windowsx86-64" - ] - }, - { - "groupId": "com.reduxrobotics.frc", - "artifactId": "ReduxLib-driver", - "version": "2025.0.0", - "libName": "ReduxCore", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "linuxathena", - "linuxx86-64", - "linuxarm32", - "linuxarm64", - "osxuniversal", - "windowsx86-64" - ] - } - ] -} \ No newline at end of file diff --git a/vendordeps/ReduxLib-2025.0.1.json b/vendordeps/ReduxLib-2025.0.1.json new file mode 100644 index 0000000..6cc750e --- /dev/null +++ b/vendordeps/ReduxLib-2025.0.1.json @@ -0,0 +1,72 @@ +{ + "fileName": "ReduxLib-2025.0.1.json", + "name": "ReduxLib", + "version": "2025.0.1", + "frcYear": "2025", + "uuid": "151ecca8-670b-4026-8160-cdd2679ef2bd", + "mavenUrls": [ + "https://maven.reduxrobotics.com/" + ], + "jsonUrl": "https://frcsdk.reduxrobotics.com/ReduxLib_2025.json", + "javaDependencies": [ + { + "groupId": "com.reduxrobotics.frc", + "artifactId": "ReduxLib-java", + "version": "2025.0.1" + } + ], + "jniDependencies": [ + { + "groupId": "com.reduxrobotics.frc", + "artifactId": "ReduxLib-driver", + "version": "2025.0.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "linuxathena", + "linuxx86-64", + "linuxarm32", + "linuxarm64", + "osxuniversal", + "windowsx86-64" + ] + } + ], + "cppDependencies": [ + { + "groupId": "com.reduxrobotics.frc", + "artifactId": "ReduxLib-cpp", + "version": "2025.0.1", + "libName": "ReduxLib", + "headerClassifier": "headers", + "sourcesClassifier": "sources", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena", + "linuxx86-64", + "linuxarm32", + "linuxarm64", + "osxuniversal", + "windowsx86-64" + ] + }, + { + "groupId": "com.reduxrobotics.frc", + "artifactId": "ReduxLib-driver", + "version": "2025.0.1", + "libName": "ReduxCore", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena", + "linuxx86-64", + "linuxarm32", + "linuxarm64", + "osxuniversal", + "windowsx86-64" + ] + } + ] +} \ No newline at end of file diff --git a/vendordeps/ThriftyLib.json b/vendordeps/ThriftyLib.json index 7b29626..93fde22 100644 --- a/vendordeps/ThriftyLib.json +++ b/vendordeps/ThriftyLib.json @@ -1,20 +1,20 @@ { - "fileName": "ThriftyLib.json", - "name": "ThriftyLib", - "version": "2025.0.2", - "frcYear": "2025", - "uuid": "60b2694b-9e6e-4026-81ee-6f167946f4b0", - "mavenUrls": [ - "https://docs.home.thethriftybot.com" - ], - "jsonUrl": "https://docs.home.thethriftybot.com/ThriftyLib.json", - "javaDependencies": [ - { - "groupId": "com.thethriftybot.frc", - "artifactId": "ThriftyLib-java", - "version": "2025.0.2" - } - ], - "jniDependencies": [], - "cppDependencies": [] + "fileName": "ThriftyLib.json", + "name": "ThriftyLib", + "version": "2025.1.0", + "frcYear": "2025", + "uuid": "60b2694b-9e6e-4026-81ee-6f167946f4b0", + "mavenUrls": [ + "https://docs.home.thethriftybot.com" + ], + "jsonUrl": "https://docs.home.thethriftybot.com/ThriftyLib.json", + "javaDependencies": [ + { + "groupId": "com.thethriftybot.frc", + "artifactId": "ThriftyLib-java", + "version": "2025.1.0" + } + ], + "jniDependencies": [], + "cppDependencies": [] } \ No newline at end of file diff --git a/vendordeps/maple-sim.json b/vendordeps/maple-sim.json index a524490..a6ee6d7 100644 --- a/vendordeps/maple-sim.json +++ b/vendordeps/maple-sim.json @@ -1,7 +1,7 @@ { "fileName": "maple-sim.json", "name": "maplesim", - "version": "0.3.2", + "version": "0.3.10", "frcYear": "2025", "uuid": "c39481e8-4a63-4a4c-9df6-48d91e4da37b", "mavenUrls": [ @@ -13,7 +13,7 @@ { "groupId": "org.ironmaple", "artifactId": "maplesim-java", - "version": "0.3.2" + "version": "0.3.10" }, { "groupId": "org.dyn4j", diff --git a/vendordeps/photonlib.json b/vendordeps/photonlib.json index 28ce4f4..6bc95c7 100644 --- a/vendordeps/photonlib.json +++ b/vendordeps/photonlib.json @@ -1,71 +1,71 @@ { - "fileName": "photonlib.json", - "name": "photonlib", - "version": "v2025.1.1", - "uuid": "515fe07e-bfc6-11fa-b3de-0242ac130004", - "frcYear": "2025", - "mavenUrls": [ - "https://maven.photonvision.org/repository/internal", - "https://maven.photonvision.org/repository/snapshots" - ], - "jsonUrl": "https://maven.photonvision.org/repository/internal/org/photonvision/photonlib-json/1.0/photonlib-json-1.0.json", - "jniDependencies": [ - { - "groupId": "org.photonvision", - "artifactId": "photontargeting-cpp", - "version": "v2025.1.1", - "skipInvalidPlatforms": true, - "isJar": false, - "validPlatforms": [ - "windowsx86-64", - "linuxathena", - "linuxx86-64", - "osxuniversal" - ] - } - ], - "cppDependencies": [ - { - "groupId": "org.photonvision", - "artifactId": "photonlib-cpp", - "version": "v2025.1.1", - "libName": "photonlib", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxathena", - "linuxx86-64", - "osxuniversal" - ] - }, - { - "groupId": "org.photonvision", - "artifactId": "photontargeting-cpp", - "version": "v2025.1.1", - "libName": "photontargeting", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxathena", - "linuxx86-64", - "osxuniversal" - ] - } - ], - "javaDependencies": [ - { - "groupId": "org.photonvision", - "artifactId": "photonlib-java", - "version": "v2025.1.1" - }, - { - "groupId": "org.photonvision", - "artifactId": "photontargeting-java", - "version": "v2025.1.1" - } - ] + "fileName": "photonlib.json", + "name": "photonlib", + "version": "v2025.3.1-rc1", + "uuid": "515fe07e-bfc6-11fa-b3de-0242ac130004", + "frcYear": "2025", + "mavenUrls": [ + "https://maven.photonvision.org/repository/internal", + "https://maven.photonvision.org/repository/snapshots" + ], + "jsonUrl": "https://maven.photonvision.org/repository/internal/org/photonvision/photonlib-json/1.0/photonlib-json-1.0.json", + "jniDependencies": [ + { + "groupId": "org.photonvision", + "artifactId": "photontargeting-cpp", + "version": "v2025.3.1-rc1", + "skipInvalidPlatforms": true, + "isJar": false, + "validPlatforms": [ + "windowsx86-64", + "linuxathena", + "linuxx86-64", + "osxuniversal" + ] + } + ], + "cppDependencies": [ + { + "groupId": "org.photonvision", + "artifactId": "photonlib-cpp", + "version": "v2025.3.1-rc1", + "libName": "photonlib", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxathena", + "linuxx86-64", + "osxuniversal" + ] + }, + { + "groupId": "org.photonvision", + "artifactId": "photontargeting-cpp", + "version": "v2025.3.1-rc1", + "libName": "photontargeting", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxathena", + "linuxx86-64", + "osxuniversal" + ] + } + ], + "javaDependencies": [ + { + "groupId": "org.photonvision", + "artifactId": "photonlib-java", + "version": "v2025.3.1-rc1" + }, + { + "groupId": "org.photonvision", + "artifactId": "photontargeting-java", + "version": "v2025.3.1-rc1" + } + ] } \ No newline at end of file diff --git a/vendordeps/yagsl-2025.2.2.json b/vendordeps/yagsl-2025.2.2.json deleted file mode 100644 index 23386f5..0000000 --- a/vendordeps/yagsl-2025.2.2.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "fileName": "yagsl-2025.2.2.json", - "name": "YAGSL", - "version": "2025.2.2", - "frcYear": "2025", - "uuid": "1ccce5a4-acd2-4d18-bca3-4b8047188400", - "mavenUrls": [ - "https://broncbotz3481.github.io/YAGSL-Lib/yagsl/repos" - ], - "jsonUrl": "https://broncbotz3481.github.io/YAGSL-Lib/yagsl/yagsl.json", - "javaDependencies": [ - { - "groupId": "swervelib", - "artifactId": "YAGSL-java", - "version": "2025.2.2" - } - ], - "requires": [ - { - "uuid": "3f48eb8c-50fe-43a6-9cb7-44c86353c4cb", - "errorMessage": "REVLib is required!", - "offlineFileName": "REVLib-2025.0.0.json", - "onlineUrl": "https://software-metadata.revrobotics.com/REVLib-2025.json" - }, - { - "uuid": "151ecca8-670b-4026-8160-cdd2679ef2bd", - "errorMessage": "ReduxLib is required!", - "offlineFileName": "ReduxLib-2025.0.0.json", - "onlineUrl": "https://frcsdk.reduxrobotics.com/ReduxLib_2025.json" - }, - { - "uuid": "e995de00-2c64-4df5-8831-c1441420ff19", - "errorMessage": "Phoenix6 is required!", - "offlineFileName": "Phoenix6-25.1.0.json", - "onlineUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix6/latest/Phoenix6-frc2025-latest.json" - }, - { - "uuid": "ab676553-b602-441f-a38d-f1296eff6537", - "errorMessage": "Phoenix5 is required!", - "offlineFileName": "Phoenix5-5.35.0.json", - "onlineUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix/Phoenix5-frc2025-latest.json" - }, - { - "uuid": "cb311d09-36e9-4143-a032-55bb2b94443b", - "errorMessage": "Studica is required!", - "offlineFileName": "Studica-2025.0.0.json", - "onlineUrl": "https://dev.studica.com/releases/2025/Studica-2025.0.0.json" - }, - { - "uuid": "60b2694b-9e6e-4026-81ee-6f167946f4b0", - "errorMessage": "ThriftyLib is required!", - "offlineFileName": "ThriftyLib.json", - "onlineUrl": "https://docs.home.thethriftybot.com/ThriftyLib.json" - }, - { - "uuid": "c39481e8-4a63-4a4c-9df6-48d91e4da37b", - "errorMessage": "maple-sim is required for simulation", - "offlineFileName": "maple-sim.json", - "onlineUrl": "https://shenzhen-robotics-alliance.github.io/maple-sim/vendordep/maple-sim.json" - } - ], - "jniDependencies": [], - "cppDependencies": [] -} \ No newline at end of file diff --git a/vendordeps/yagsl-2025.7.2.json b/vendordeps/yagsl-2025.7.2.json new file mode 100644 index 0000000..9fb6a48 --- /dev/null +++ b/vendordeps/yagsl-2025.7.2.json @@ -0,0 +1,64 @@ +{ + "fileName": "yagsl-2025.7.2.json", + "name": "YAGSL", + "version": "2025.7.2", + "frcYear": "2025", + "uuid": "1ccce5a4-acd2-4d18-bca3-4b8047188400", + "mavenUrls": [ + "https://broncbotz3481.github.io/YAGSL-Lib/yagsl/repos" + ], + "jsonUrl": "https://broncbotz3481.github.io/YAGSL-Lib/yagsl/yagsl.json", + "javaDependencies": [ + { + "groupId": "swervelib", + "artifactId": "YAGSL-java", + "version": "2025.7.2" + } + ], + "requires": [ + { + "uuid": "3f48eb8c-50fe-43a6-9cb7-44c86353c4cb", + "errorMessage": "REVLib is required!", + "offlineFileName": "REVLib-2025.0.0.json", + "onlineUrl": "https://software-metadata.revrobotics.com/REVLib-2025.json" + }, + { + "uuid": "151ecca8-670b-4026-8160-cdd2679ef2bd", + "errorMessage": "ReduxLib is required!", + "offlineFileName": "ReduxLib-2025.0.0.json", + "onlineUrl": "https://frcsdk.reduxrobotics.com/ReduxLib_2025.json" + }, + { + "uuid": "e995de00-2c64-4df5-8831-c1441420ff19", + "errorMessage": "Phoenix6 is required!", + "offlineFileName": "Phoenix6-25.1.0.json", + "onlineUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix6/latest/Phoenix6-frc2025-latest.json" + }, + { + "uuid": "ab676553-b602-441f-a38d-f1296eff6537", + "errorMessage": "Phoenix5 is required!", + "offlineFileName": "Phoenix5-5.35.0.json", + "onlineUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix/Phoenix5-frc2025-latest.json" + }, + { + "uuid": "cb311d09-36e9-4143-a032-55bb2b94443b", + "errorMessage": "Studica is required!", + "offlineFileName": "Studica-2025.0.0.json", + "onlineUrl": "https://dev.studica.com/releases/2025/Studica-2025.0.0.json" + }, + { + "uuid": "60b2694b-9e6e-4026-81ee-6f167946f4b0", + "errorMessage": "ThriftyLib is required!", + "offlineFileName": "ThriftyLib.json", + "onlineUrl": "https://docs.home.thethriftybot.com/ThriftyLib.json" + }, + { + "uuid": "c39481e8-4a63-4a4c-9df6-48d91e4da37b", + "errorMessage": "maple-sim is required for simulation", + "offlineFileName": "maple-sim.json", + "onlineUrl": "https://shenzhen-robotics-alliance.github.io/maple-sim/vendordep/maple-sim.json" + } + ], + "jniDependencies": [], + "cppDependencies": [] +} \ No newline at end of file