diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 6bafd3d..4f76cc2 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -15,11 +15,13 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up JDK 1.17 - uses: actions/setup-java@v1 + - uses: actions/checkout@v7 + - name: Set up JDK 25 + uses: actions/setup-java@v6 with: - java-version: 1.17 + distribution: 'temurin' + java-version: '25' + cache: 'gradle' - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Build with Gradle diff --git a/.gitignore b/.gitignore index 11d4e4f..3145f39 100644 --- a/.gitignore +++ b/.gitignore @@ -158,9 +158,34 @@ gradle-app.setting .settings/ bin/ +# IntelliJ +*.iml +*.ipr +*.iws +.idea/ +out/ + +# Fleet +.fleet + # Simulation GUI and other tools window save file +networktables.json +simgui.json *-window.json +# Simulation data log directory +logs/ + # Logs *.wpilog *.log + +# Folder that has CTRE Phoenix Sim device config storage +ctre_sim/ + +# clangd +/.cache +compile_commands.json + +# Eclipse generated file for annotation processors +.factorypath diff --git a/.vscode/settings.json b/.vscode/settings.json index 4ed293b..3c5c2e6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -25,5 +25,37 @@ } }, ], - "java.test.defaultConfig": "WPIlibUnitTests" + "java.test.defaultConfig": "WPIlibUnitTests", + "java.import.gradle.annotationProcessing.enabled": false, + "java.completion.favoriteStaticMembers": [ + "org.junit.Assert.*", + "org.junit.Assume.*", + "org.junit.jupiter.api.Assertions.*", + "org.junit.jupiter.api.Assumptions.*", + "org.junit.jupiter.api.DynamicContainer.*", + "org.junit.jupiter.api.DynamicTest.*", + "org.mockito.Mockito.*", + "org.mockito.ArgumentMatchers.*", + "org.mockito.Answers.*", + "org.wpilib.units.Units.*" + ], + "java.completion.filteredTypes": [ + "java.awt.*", + "com.sun.*", + "sun.*", + "jdk.*", + "org.graalvm.*", + "io.micrometer.shaded.*", + "java.beans.*", + "java.util.Base64.*", + "java.util.Timer", + "java.sql.*", + "javax.swing.*", + "javax.management.*", + "javax.smartcardio.*", + "org.wpilib.math.proto.*", + "org.wpilib.math.**.proto.*", + "org.wpilib.math.**.struct.*", + ], + "java.dependency.enableDependencyCheckup": false } diff --git a/.wpilib/wpilib_preferences.json b/.wpilib/wpilib_preferences.json index 1775a01..aed4426 100644 --- a/.wpilib/wpilib_preferences.json +++ b/.wpilib/wpilib_preferences.json @@ -1,6 +1,6 @@ { "enableCppIntellisense": false, "currentLanguage": "java", - "projectYear": "2026", + "projectYear": "2027_alpha5", "teamNumber": 694 } \ No newline at end of file diff --git a/LICENSE b/LICENSE index 10fb5b1..71f9aa7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 StuyPulse +Copyright (c) 2026 StuyPulse Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index d70ff1f..84c0e3a 100644 --- a/README.md +++ b/README.md @@ -13,5 +13,4 @@ Do *not* use the automatic import project tool. Instead, - Change the 'frcYear' to the current year in `settings.gradle`. - Check that the `GradleRIO` version is up to date in `./build.gradle`. - Check the latest version of [StuyLib here](https://github.com/StuyPulse/StuyLib/releases) and update the version in `./build.gradle`. -- Manually update the files ('frcYear', 'version', URLS) in `./venderdeps` with their latest version, checking their respective websites, or import new versions using WPILib vendor dependencies. - +- Manually update the files ('frcYear', 'version', URLS) in `./vendordeps` with their latest version, checking their respective websites, or import new versions using WPILib vendor dependencies. diff --git a/WPILib-License.md b/WPILib-License.md index 645e542..eb3061b 100644 --- a/WPILib-License.md +++ b/WPILib-License.md @@ -1,4 +1,4 @@ -Copyright (c) 2009-2024 FIRST and other WPILib contributors +Copyright (c) 2009-2026 FIRST and other WPILib contributors All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/assets/.gitkeep b/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/build.gradle b/build.gradle index 1ff6551..1d67b9c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,68 +1,72 @@ plugins { id "java" - id "edu.wpi.first.GradleRIO" version "2026.2.1" - id "com.diffplug.spotless" version "6.22.0" + id "org.wpilib.GradleRIO" version "2027.0.0-alpha-6" + id "com.gradleup.shadow" version "9.3.0" + id "com.diffplug.spotless" version "8.9.0" } -allprojects { - repositories { - maven { url 'https://jitpack.io' } - } +java { + sourceCompatibility = JavaVersion.VERSION_25 + targetCompatibility = JavaVersion.VERSION_25 } def ROBOT_MAIN_CLASS = "com.stuypulse.robot.Main" -sourceCompatibility = JavaVersion.VERSION_17 -targetCompatibility = JavaVersion.VERSION_17 - -// Define my targets (RoboRIO) and artifacts (deployable files) +// Define my targets (SystemCore) and artifacts (deployable files) // This is added by GradleRIO's backing project DeployUtils. deploy { targets { - roborio(getTargetTypeClass('RoboRIO')) { + systemcore(getTargetTypeClass('SystemCore')) { // Team number is loaded either from the .wpilib/wpilib_preferences.json // or from command line. If not found an exception will be thrown. // You can use getTeamOrDefault(team) instead of getTeamNumber if you // want to store a team number in this file. - team = project.frc.getTeamNumber() - debug = project.frc.getDebugOrDefault(false) + team = project.wpilib.getTeamNumber() + // Use the default systemcore host name. This must be called after setting team + // as happens on the line above + useDefaultSystemcoreHostName() + debug = project.wpilib.getDebugOrDefault(false) artifacts { // First part is artifact name, 2nd is artifact type // getTargetTypeClass is a shortcut to get the class type using a string - frcJava(getArtifactTypeClass('FRCJavaArtifact')) { + wpilibJava(getArtifactTypeClass('WPILibJavaArtifact')) { } // Static files artifact - frcStaticFileDeploy(getArtifactTypeClass('FileTreeArtifact')) { + wpilibStaticFileDeploy(getArtifactTypeClass('FileTreeArtifact')) { files = project.fileTree('src/main/deploy') - directory = '/home/lvuser/deploy' + directory = '/home/systemcore/deploy' + deleteOldFiles = false // Change to true to delete files on systemcore that no + // longer exist in deploy directory of this project } } } } } -def deployArtifact = deploy.targets.roborio.artifacts.frcJava +def deployArtifact = deploy.targets.systemcore.artifacts.wpilibJava -// Set to true to use debug for JNI. +// Set to true to use debug for all targets including JNI, which will drastically impact +// performance. wpi.java.debugJni = false // Set this to true to enable desktop support. -def includeDesktopSupport = false +def includeDesktopSupport = true // Defining my dependencies. In this case, WPILib (+ friends), and vendor libraries. // Also defines JUnit 5. dependencies { + annotationProcessor wpi.java.deps.wpilibAnnotations() implementation wpi.java.deps.wpilib() implementation wpi.java.vendor.java() - roborioDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.roborio) - roborioDebug wpi.java.vendor.jniDebug(wpi.platforms.roborio) + systemcoreDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.systemcore) + systemcoreDebug wpi.java.vendor.jniDebug(wpi.platforms.systemcore) - roborioRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.roborio) - roborioRelease wpi.java.vendor.jniRelease(wpi.platforms.roborio) + systemcoreRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.systemcore) + systemcoreRelease wpi.java.vendor.jniRelease(wpi.platforms.systemcore) nativeDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.desktop) nativeDebug wpi.java.vendor.jniDebug(wpi.platforms.desktop) @@ -72,18 +76,51 @@ dependencies { nativeRelease wpi.java.vendor.jniRelease(wpi.platforms.desktop) simulationRelease wpi.sim.enableRelease() - testImplementation 'junit:junit:4.13.1' + testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' +} + +test { + useJUnitPlatform() + systemProperty 'junit.jupiter.extensions.autodetection.enabled', 'true' } // Simulation configuration (e.g. environment variables). wpi.sim.addGui().defaultEnabled = true wpi.sim.addDriverstation() +// Setting up my Jar File. In this case, adding all libraries into the main jar ('fat/shaded jar') +// in order to make them all available at runtime and merging service files to make JSON work. +// Also adding the manifest so WPILib knows where to look for our Robot Class. +shadowJar { + mergeServiceFiles() + from('src') { into 'backup/src' } + from('vendordeps') { into 'backup/vendordeps' } + from('build.gradle') { into 'backup' } + manifest org.wpilib.gradlerio.GradleRIOPlugin.javaManifest(ROBOT_MAIN_CLASS) + duplicatesStrategy = DuplicatesStrategy.INCLUDE +} + +// Configure jar and deploy tasks +deployArtifact.jarTask = shadowJar +wpi.java.configureExecutableTasks(shadowJar) +wpi.java.configureTestTasks(test) + +// Configure string concat to always inline compile +tasks.withType(JavaCompile) { + options.compilerArgs.add '-XDstringConcat=inline' +} + spotless { enforceCheck = false java { targetExclude("src/main/java/com/stuypulse/robot/commands/autons/*.java") - licenseHeaderFile "LICENSE" + + licenseHeader("""/************************ PROJECT PHIL ************************/ +/* Copyright (c) 2026 StuyPulse Robotics. All rights reserved.*/ +/* This work is licensed under the terms of the MIT license. */ +/**************************************************************/ +""").updateYearWithLatest(false) googleJavaFormat().aosp() @@ -97,28 +134,9 @@ spotless { 'com.stuypulse.commands.auton', 'com.stuypulse.util', 'com.stuypulse', - 'edu.wpi', + 'org.wpilib', 'com.revrobotics' ) removeUnusedImports() } } - -// Setting up my Jar File. In this case, adding all libraries into the main jar ('fat jar') -// in order to make them all available at runtime. Also adding the manifest so WPILib -// knows where to look for our Robot Class. -jar { - from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } - manifest edu.wpi.first.gradlerio.GradleRIOPlugin.javaManifest(ROBOT_MAIN_CLASS) - duplicatesStrategy = DuplicatesStrategy.INCLUDE -} - -// Configure jar and deploy tasks -deployArtifact.jarTask = jar -wpi.java.configureExecutableTasks(jar) -wpi.java.configureTestTasks(test) - -// Configure string concat to always inline compile -tasks.withType(JavaCompile) { - options.compilerArgs.add '-XDstringConcat=inline' -} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index a4b76b9..d997cfc 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 34bd9ce..42bb5ac 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=permwrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index f5feea6..0c908af 100755 --- a/gradlew +++ b/gradlew @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/2d6327017519d23b96af35865dc997fcb544fb40/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -115,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -173,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -206,15 +203,14 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9d21a21..c4bdd3a 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,10 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/settings.gradle b/settings.gradle index 486702a..e2626a8 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,27 +2,27 @@ import org.gradle.internal.os.OperatingSystem pluginManagement { repositories { - mavenLocal() - gradlePluginPortal() - String frcYear = '2026' - File frcHome + String wpilibYear = '2027_alpha5' + File wpilibHome if (OperatingSystem.current().isWindows()) { String publicFolder = System.getenv('PUBLIC') if (publicFolder == null) { publicFolder = "C:\\Users\\Public" } def homeRoot = new File(publicFolder, "wpilib") - frcHome = new File(homeRoot, frcYear) + wpilibHome = new File(homeRoot, wpilibYear) } else { def userFolder = System.getProperty("user.home") def homeRoot = new File(userFolder, "wpilib") - frcHome = new File(homeRoot, frcYear) + wpilibHome = new File(homeRoot, wpilibYear) } - def frcHomeMaven = new File(frcHome, 'maven') + def wpilibHomeMaven = new File(wpilibHome, 'maven') maven { - name 'frcHome' - url frcHomeMaven + name = 'wpilibHome' + url = wpilibHomeMaven } + mavenLocal() + gradlePluginPortal() } } diff --git a/src/main/deploy/.gitkeep b/src/main/deploy/.gitkeep index bb82515..e69de29 100644 --- a/src/main/deploy/.gitkeep +++ b/src/main/deploy/.gitkeep @@ -1,3 +0,0 @@ -Files placed in this directory will be deployed to the RoboRIO into the -'deploy' directory in the home folder. Use the 'Filesystem.getDeployDirectory' wpilib function -to get a proper path relative to the deploy directory. \ No newline at end of file diff --git a/src/main/java/com/stuypulse/robot/Main.java b/src/main/java/com/stuypulse/robot/Main.java index a4f5843..f7c261e 100644 --- a/src/main/java/com/stuypulse/robot/Main.java +++ b/src/main/java/com/stuypulse/robot/Main.java @@ -1,16 +1,25 @@ /************************ PROJECT PHIL ************************/ -/* Copyright (c) 2024 StuyPulse Robotics. All rights reserved.*/ +/* Copyright (c) 2026 StuyPulse Robotics. All rights reserved.*/ /* This work is licensed under the terms of the MIT license. */ /**************************************************************/ - package com.stuypulse.robot; -import edu.wpi.first.wpilibj.RobotBase; +import org.wpilib.framework.RobotBase; +/** + * Main Class + * + * This is the main class that instantiates the robot code. + * There is no need to edit this file, and it should not be edited unless you know what you are doing. + */ public final class Main { private Main() {} + /** + * The main method that starts the robot code. This should not be edited unless you know what + * you are doing. + */ public static void main(String... args) { - RobotBase.startRobot(Robot::new); + RobotBase.startRobot(Robot.class); } } diff --git a/src/main/java/com/stuypulse/robot/Robot.java b/src/main/java/com/stuypulse/robot/Robot.java index e0f788d..40ee44f 100644 --- a/src/main/java/com/stuypulse/robot/Robot.java +++ b/src/main/java/com/stuypulse/robot/Robot.java @@ -1,31 +1,55 @@ /************************ PROJECT PHIL ************************/ -/* Copyright (c) 2024 StuyPulse Robotics. All rights reserved.*/ +/* Copyright (c) 2026 StuyPulse Robotics. All rights reserved.*/ /* This work is licensed under the terms of the MIT license. */ /**************************************************************/ - package com.stuypulse.robot; -import edu.wpi.first.wpilibj.TimedRobot; -import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.CommandScheduler; - +import org.wpilib.command3.Command; +import org.wpilib.command3.Scheduler; +import org.wpilib.driverstation.Alliance; +import org.wpilib.driverstation.MatchState; +import org.wpilib.framework.TimedRobot; + +import java.util.Optional; + +/** + * Robot Class + * + * This is the main class for robot code, instantiated in {@link com.stuypulse.robot.Main} It + * extends TimedRobot, meaning that the methods in this class are called automatically during + * specific states of the robot. + */ public class Robot extends TimedRobot { + /** + * Checks the alliance the robot is on + * + * @return true if the robot is on the blue alliance, false if the robot is on the red alliance, + * and false if alliance cannot be determined. + */ + public static boolean isBlue() { + final Optional alliance = MatchState.getAlliance(); + if (alliance.isPresent()) { + return alliance.get() == Alliance.BLUE; + } + return false; + } - private RobotContainer robot; + private final RobotContainer robot; + private final Scheduler defaultScheduler; private Command auto; + public Robot() { + robot = new RobotContainer(); + defaultScheduler = Scheduler.getDefault(); + } + /*************************/ /*** ROBOT SCHEDULEING ***/ /*************************/ - @Override - public void robotInit() { - robot = new RobotContainer(); - } - @Override public void robotPeriodic() { - CommandScheduler.getInstance().run(); + defaultScheduler.run(); } /*********************/ @@ -40,14 +64,14 @@ public void disabledPeriodic() {} /***********************/ /*** AUTONOMOUS MODE ***/ - /***********************/ + /***********************/ @Override public void autonomousInit() { auto = robot.getAutonomousCommand(); if (auto != null) { - auto.schedule(); + defaultScheduler.schedule(auto); } } @@ -64,7 +88,7 @@ public void autonomousExit() {} @Override public void teleopInit() { if (auto != null) { - auto.cancel(); + defaultScheduler.cancel(auto); } } @@ -74,18 +98,18 @@ public void teleopPeriodic() {} @Override public void teleopExit() {} - /*****************/ - /*** TEST MODE ***/ - /*****************/ + /*************************/ + /*** UTILITY/TEST MODE ***/ + /*************************/ @Override - public void testInit() { - CommandScheduler.getInstance().cancelAll(); + public void utilityInit() { + defaultScheduler.cancelAll(); } @Override - public void testPeriodic() {} + public void utilityPeriodic() {} @Override - public void testExit() {} + public void utilityExit() {} } diff --git a/src/main/java/com/stuypulse/robot/RobotContainer.java b/src/main/java/com/stuypulse/robot/RobotContainer.java index c48fa38..d4aa08b 100644 --- a/src/main/java/com/stuypulse/robot/RobotContainer.java +++ b/src/main/java/com/stuypulse/robot/RobotContainer.java @@ -1,24 +1,28 @@ /************************ PROJECT PHIL ************************/ -/* Copyright (c) 2024 StuyPulse Robotics. All rights reserved.*/ +/* Copyright (c) 2026 StuyPulse Robotics. All rights reserved.*/ /* This work is licensed under the terms of the MIT license. */ /**************************************************************/ - package com.stuypulse.robot; -import com.stuypulse.robot.commands.auton.DoNothingAuton; +import com.stuypulse.robot.commands.auton.AutonomousRoutines; import com.stuypulse.robot.constants.Ports; -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.button.CommandXboxController; +import org.wpilib.command3.Command; +import org.wpilib.command3.button.CommandNiDsXboxController; +import org.wpilib.smartdashboard.SendableChooser; +import org.wpilib.smartdashboard.SmartDashboard; + +import dev.doglog.DogLog; +import dev.doglog.DogLogOptions; public class RobotContainer { // Gamepads - public final CommandXboxController driver = new CommandXboxController(Ports.Gamepad.DRIVER); - public final CommandXboxController operator = new CommandXboxController(Ports.Gamepad.OPERATOR); - + public final CommandNiDsXboxController driver = + new CommandNiDsXboxController(Ports.Gamepad.DRIVER); + public final CommandNiDsXboxController operator = + new CommandNiDsXboxController(Ports.Gamepad.OPERATOR); + // Subsystem // Autons @@ -27,11 +31,21 @@ public class RobotContainer { // Robot container public RobotContainer() { + configureLogging(); configureDefaultCommands(); configureButtonBindings(); configureAutons(); } + /***************/ + /*** LOGGING ***/ + /***************/ + + private void configureLogging() { + DogLog.setOptions( + new DogLogOptions().withCaptureDs(true).withNtTunables(true).withLogExtras(true)); + } + /****************/ /*** DEFAULTS ***/ /****************/ @@ -49,11 +63,16 @@ private void configureButtonBindings() {} /**************/ public void configureAutons() { - autonChooser.setDefaultOption("Do Nothing", new DoNothingAuton()); + autonChooser.setDefaultOption("Do Nothing", AutonomousRoutines.doNothingAuton()); SmartDashboard.putData("Autonomous", autonChooser); } + /** + * Use this to pass the autonomous command to the main {@link Robot} class. + * + * @return The command to run in autonomous + */ public Command getAutonomousCommand() { return autonChooser.getSelected(); } diff --git a/src/main/java/com/stuypulse/robot/commands/DoNothingCommand.java b/src/main/java/com/stuypulse/robot/commands/DoNothingCommand.java deleted file mode 100644 index 5b653f7..0000000 --- a/src/main/java/com/stuypulse/robot/commands/DoNothingCommand.java +++ /dev/null @@ -1,25 +0,0 @@ -/************************ PROJECT PHIL ************************/ -/* Copyright (c) 2024 StuyPulse Robotics. All rights reserved.*/ -/* This work is licensed under the terms of the MIT license. */ -/**************************************************************/ - -package com.stuypulse.robot.commands; - -import edu.wpi.first.wpilibj2.command.InstantCommand; - -/*- - * This command does a whole load of nothing... - * - * @author Ivan Chen - */ -public class DoNothingCommand extends InstantCommand { - - public DoNothingCommand() { - // Do loads of nothing - } - - @Override - public void initialize() { - // Do loads of nothing - } -} diff --git a/src/main/java/com/stuypulse/robot/commands/auton/AutonomousRoutines.java b/src/main/java/com/stuypulse/robot/commands/auton/AutonomousRoutines.java new file mode 100644 index 0000000..3fa7df7 --- /dev/null +++ b/src/main/java/com/stuypulse/robot/commands/auton/AutonomousRoutines.java @@ -0,0 +1,13 @@ +/************************ PROJECT PHIL ************************/ +/* Copyright (c) 2026 StuyPulse Robotics. All rights reserved.*/ +/* This work is licensed under the terms of the MIT license. */ +/**************************************************************/ +package com.stuypulse.robot.commands.auton; + +import org.wpilib.command3.Command; + +public interface AutonomousRoutines { + public static Command doNothingAuton() { + return Command.sequence().named("Do Nothing"); + } +} diff --git a/src/main/java/com/stuypulse/robot/commands/auton/DoNothingAuton.java b/src/main/java/com/stuypulse/robot/commands/auton/DoNothingAuton.java deleted file mode 100644 index 1d07398..0000000 --- a/src/main/java/com/stuypulse/robot/commands/auton/DoNothingAuton.java +++ /dev/null @@ -1,22 +0,0 @@ -/************************ PROJECT PHIL ************************/ -/* Copyright (c) 2024 StuyPulse Robotics. All rights reserved.*/ -/* This work is licensed under the terms of the MIT license. */ -/**************************************************************/ - -package com.stuypulse.robot.commands.auton; - -import edu.wpi.first.wpilibj2.command.SequentialCommandGroup; - -/*- - * This auton does nothing... it is used as a placeholder - * - * @author Sam Belliveau - */ -public class DoNothingAuton extends SequentialCommandGroup { - - public DoNothingAuton() { - addCommands( - /** Do a whole lot of nothing */ - ); - } -} \ No newline at end of file diff --git a/src/main/java/com/stuypulse/robot/constants/Motors.java b/src/main/java/com/stuypulse/robot/constants/Motors.java index dc36e23..06a75ce 100644 --- a/src/main/java/com/stuypulse/robot/constants/Motors.java +++ b/src/main/java/com/stuypulse/robot/constants/Motors.java @@ -1,32 +1,16 @@ /************************ PROJECT PHIL ************************/ -/* Copyright (c) 2024 StuyPulse Robotics. All rights reserved.*/ +/* Copyright (c) 2026 StuyPulse Robotics. All rights reserved.*/ /* This work is licensed under the terms of the MIT license. */ /**************************************************************/ - package com.stuypulse.robot.constants; -import com.ctre.phoenix6.configs.ClosedLoopGeneralConfigs; -import com.ctre.phoenix6.configs.ClosedLoopRampsConfigs; -import com.ctre.phoenix6.configs.CurrentLimitsConfigs; -import com.ctre.phoenix6.configs.FeedbackConfigs; -import com.ctre.phoenix6.configs.MotionMagicConfigs; -import com.ctre.phoenix6.configs.MotorOutputConfigs; -import com.ctre.phoenix6.configs.OpenLoopRampsConfigs; -import com.ctre.phoenix6.configs.Slot0Configs; -import com.ctre.phoenix6.configs.Slot1Configs; -import com.ctre.phoenix6.configs.Slot2Configs; -import com.ctre.phoenix6.configs.SlotConfigs; -import com.ctre.phoenix6.configs.SoftwareLimitSwitchConfigs; -import com.ctre.phoenix6.configs.TalonFXConfiguration; -import com.ctre.phoenix6.configs.TorqueCurrentConfigs; -import com.ctre.phoenix6.configs.VoltageConfigs; +import static org.wpilib.units.Units.*; + +import org.wpilib.units.measure.*; + +import com.ctre.phoenix6.configs.*; import com.ctre.phoenix6.hardware.TalonFX; -import com.ctre.phoenix6.signals.FeedbackSensorSourceValue; -import com.ctre.phoenix6.signals.GainSchedBehaviorValue; -import com.ctre.phoenix6.signals.GravityTypeValue; -import com.ctre.phoenix6.signals.InvertedValue; -import com.ctre.phoenix6.signals.NeutralModeValue; -import com.ctre.phoenix6.signals.StaticFeedforwardSignValue; +import com.ctre.phoenix6.signals.*; /*- * File containing all of the configurations that different motors require. @@ -40,9 +24,7 @@ public interface Motors { /** Classes to store all of the values a motor needs */ - /** - * Wrapper class for configuring TalonFX motors - */ + /** Wrapper class for configuring TalonFX motors */ public static class TalonFXConfig { private final TalonFXConfiguration configuration = new TalonFXConfiguration(); private final Slot0Configs slot0Configs = new Slot0Configs(); @@ -54,8 +36,10 @@ public static class TalonFXConfig { private final CurrentLimitsConfigs currentLimitsConfigs = new CurrentLimitsConfigs(); private final FeedbackConfigs feedbackConfigs = new FeedbackConfigs(); private final MotionMagicConfigs motionMagicConfigs = new MotionMagicConfigs(); - private final SoftwareLimitSwitchConfigs softwareLimitSwitchConfigs = new SoftwareLimitSwitchConfigs(); - private final ClosedLoopGeneralConfigs closedLoopGeneralConfigs = new ClosedLoopGeneralConfigs(); + private final SoftwareLimitSwitchConfigs softwareLimitSwitchConfigs = + new SoftwareLimitSwitchConfigs(); + private final ClosedLoopGeneralConfigs closedLoopGeneralConfigs = + new ClosedLoopGeneralConfigs(); private final VoltageConfigs voltageConfigs = new VoltageConfigs(); private final TorqueCurrentConfigs torqueCurrentConfigs = new TorqueCurrentConfigs(); @@ -77,30 +61,39 @@ public TalonFXConfiguration getConfiguration() { return this.configuration; } - public void updateGainsConfig(TalonFX motor, int slot, double kP, double kI, double kD, double kS, double kV, double kA) { + public void updateGainsConfig( + TalonFX motor, + int slot, + double kP, + double kI, + double kD, + double kS, + double kV, + double kA) { if (slot != 0 && slot != 1 && slot != 2) { return; } - boolean changed = - kP != lastKP[slot] || - kI != lastKI[slot] || - kD != lastKD[slot] || - kS != lastKS[slot] || - kV != lastKV[slot] || - kA != lastKA[slot]; + final boolean changed = + kP != lastKP[slot] + || kI != lastKI[slot] + || kD != lastKD[slot] + || kS != lastKS[slot] + || kV != lastKV[slot] + || kA != lastKA[slot]; if (!changed) { return; } - SlotConfigs gainConfig = new SlotConfigs() - .withKP(kP) - .withKI(kI) - .withKD(kD) - .withKS(kS) - .withKV(kV) - .withKA(kA); + final SlotConfigs gainConfig = + new SlotConfigs() + .withKP(kP) + .withKI(kI) + .withKD(kD) + .withKS(kS) + .withKV(kV) + .withKA(kA); gainConfig.SlotNumber = slot; @@ -131,21 +124,15 @@ public void updateGainsConfig(TalonFX motor, int slot, double kP, double kI, dou public TalonFXConfig withPIDConstants(double kP, double kI, double kD, int slot) { switch (slot) { case 0: - slot0Configs.kP = kP; - slot0Configs.kI = kI; - slot0Configs.kD = kD; + slot0Configs.withKP(kP).withKI(kI).withKD(kD); configuration.withSlot0(slot0Configs); break; case 1: - slot1Configs.kP = kP; - slot1Configs.kI = kI; - slot1Configs.kD = kD; + slot1Configs.withKP(kP).withKI(kI).withKD(kD); configuration.withSlot1(slot1Configs); break; case 2: - slot2Configs.kP = kP; - slot2Configs.kI = kI; - slot2Configs.kD = kD; + slot2Configs.withKP(kP).withKI(kI).withKD(kD); configuration.withSlot2(slot2Configs); break; } @@ -159,42 +146,34 @@ public TalonFXConfig withFFConstants(double kS, double kV, double kA, int slot) public TalonFXConfig withFFConstants(double kS, double kV, double kA, double kG, int slot) { switch (slot) { case 0: - slot0Configs.kS = kS; - slot0Configs.kV = kV; - slot0Configs.kA = kA; - slot0Configs.kG = kG; + slot0Configs.withKS(kS).withKV(kV).withKA(kA).withKG(kG); configuration.withSlot0(slot0Configs); break; case 1: - slot1Configs.kS = kS; - slot1Configs.kV = kV; - slot1Configs.kA = kA; - slot1Configs.kG = kG; + slot1Configs.withKS(kS).withKV(kV).withKA(kA).withKG(kG); configuration.withSlot1(slot1Configs); break; case 2: - slot2Configs.kS = kS; - slot2Configs.kV = kV; - slot2Configs.kA = kA; - slot2Configs.kG = kG; + slot2Configs.withKS(kS).withKV(kV).withKA(kA).withKG(kG); configuration.withSlot2(slot2Configs); break; } return this; } - public TalonFXConfig withStaticFeedforwardSign(StaticFeedforwardSignValue staticFeedforwardSign, int slot) { + public TalonFXConfig withStaticFeedforwardSign( + StaticFeedforwardSignValue staticFeedforwardSign, int slot) { switch (slot) { case 0: - slot0Configs.StaticFeedforwardSign = staticFeedforwardSign; + slot0Configs.withStaticFeedforwardSign(staticFeedforwardSign); configuration.withSlot0(slot0Configs); break; case 1: - slot1Configs.StaticFeedforwardSign = staticFeedforwardSign; + slot1Configs.withStaticFeedforwardSign(staticFeedforwardSign); configuration.withSlot1(slot1Configs); break; case 2: - slot2Configs.StaticFeedforwardSign = staticFeedforwardSign; + slot2Configs.withStaticFeedforwardSign(staticFeedforwardSign); configuration.withSlot2(slot2Configs); break; } @@ -203,9 +182,9 @@ public TalonFXConfig withStaticFeedforwardSign(StaticFeedforwardSignValue static } public TalonFXConfig withGravityType(GravityTypeValue gravityType) { - slot0Configs.GravityType = gravityType; - slot1Configs.GravityType = gravityType; - slot2Configs.GravityType = gravityType; + slot0Configs.withGravityType(gravityType); + slot1Configs.withGravityType(gravityType); + slot2Configs.withGravityType(gravityType); configuration.withSlot0(slot0Configs); configuration.withSlot1(slot1Configs); @@ -214,26 +193,56 @@ public TalonFXConfig withGravityType(GravityTypeValue gravityType) { return this; } - public TalonFXConfig withGainSchedBehavior(GainSchedBehaviorValue value, double threshold, int slot) { - closedLoopGeneralConfigs.GainSchedErrorThreshold = threshold; + /** + * Modifies this configuration's GainSchedErrorThreshold parameter, which is the position + * closed-loop error threshold to apply gains scheduling. + * + * @param value Gains scheduling behavior, see {@link + * com.ctre.phoenix6.signals.GainSchedBehaviorValue}. + * @param thresholdRotations The position closed-loop error threshold for gain scheduling in + * rotations. + * @param slot Slot to apply gains scheduling behavior to. + * @return Itself for method-chaining. + */ + public TalonFXConfig withGainSchedBehavior( + GainSchedBehaviorValue value, double thresholdRotations, int slot) { + return this.withGainSchedBehavior(value, Rotations.of(thresholdRotations), slot); + } + + /** + * Modifies this configuration's GainSchedErrorThreshold parameter, which is the position + * closed-loop error threshold to apply gains scheduling. + * + * @param value Gains scheduling behavior, see {@link + * com.ctre.phoenix6.signals.GainSchedBehaviorValue}. + * @param thresholdRotations The position closed-loop error threshold for gain scheduling. + * @param slot Slot to apply gains scheduling behavior to. + * @return Itself for method-chaining. + */ + public TalonFXConfig withGainSchedBehavior( + GainSchedBehaviorValue value, Angle threshold, int slot) { + closedLoopGeneralConfigs.withGainSchedErrorThreshold(threshold); configuration.withClosedLoopGeneral(closedLoopGeneralConfigs); - - switch(slot) { - case 0: { - slot0Configs.GainSchedBehavior = value; - configuration.withSlot0(slot0Configs); - } - break; - case 1: { - slot1Configs.GainSchedBehavior = value; - configuration.withSlot1(slot1Configs); - } - break; - case 2: { - slot2Configs.GainSchedBehavior = value; - configuration.withSlot2(slot2Configs); - } - break; + + switch (slot) { + case 0: + { + slot0Configs.withGainSchedBehavior(value); + configuration.withSlot0(slot0Configs); + } + break; + case 1: + { + slot1Configs.withGainSchedBehavior(value); + configuration.withSlot1(slot1Configs); + } + break; + case 2: + { + slot2Configs.withGainSchedBehavior(value); + configuration.withSlot2(slot2Configs); + } + break; } return this; @@ -242,7 +251,7 @@ public TalonFXConfig withGainSchedBehavior(GainSchedBehaviorValue value, double // MOTOR OUTPUT CONFIGS public TalonFXConfig withInvertedValue(InvertedValue invertedValue) { - motorOutputConfigs.Inverted = invertedValue; + motorOutputConfigs.withInverted(invertedValue); configuration.withMotorOutput(motorOutputConfigs); @@ -250,15 +259,32 @@ public TalonFXConfig withInvertedValue(InvertedValue invertedValue) { } public TalonFXConfig withNeutralMode(NeutralModeValue neutralMode) { - motorOutputConfigs.NeutralMode = neutralMode; + motorOutputConfigs.withNeutralMode(neutralMode); configuration.withMotorOutput(motorOutputConfigs); return this; } - public TalonFXConfig withVelocityTimeFilter(double filterInSeconds) { - feedbackConfigs.withVelocityFilterTimeConstant(filterInSeconds); + /** + * Modifies this configuration's velocity filter's time constant. + * + * @param filterTime The configurable time constant in seconds of the Kalman velocity + * filter. + * @return Itself for easier method-chaining + */ + public TalonFXConfig withVelocityTimeFilter(double filterTimeSeconds) { + return this.withVelocityTimeFilter(Seconds.of(filterTimeSeconds)); + } + + /** + * Modifies this configuration's velocity filter's time constant. + * + * @param filterTime The configurable time constant of the Kalman velocity filter. + * @return Itself for easier method-chaining + */ + public TalonFXConfig withVelocityTimeFilter(Time filterTime) { + feedbackConfigs.withVelocityFilterTimeConstant(filterTime); configuration.withFeedback(feedbackConfigs); @@ -267,14 +293,48 @@ public TalonFXConfig withVelocityTimeFilter(double filterInSeconds) { // RAMP RATE CONFIGS - public TalonFXConfig withRampRate(double rampRate) { - closedLoopRampsConfigs.DutyCycleClosedLoopRampPeriod = rampRate; - closedLoopRampsConfigs.TorqueClosedLoopRampPeriod = rampRate; - closedLoopRampsConfigs.VoltageClosedLoopRampPeriod = rampRate; + /** + * Modifies this configuration's open and closed loop ramp periods for the following control + * types: + * + * + * + *
+ * + * @param rampRateSeconds Seconds for the motor to reach peak output from 0 + * @return Itself for method-chaining + */ + public TalonFXConfig withRampRate(double rampRateSeconds) { + return this.withRampRate(Seconds.of(rampRateSeconds)); + } - openLoopRampsConfigs.DutyCycleOpenLoopRampPeriod = rampRate; - openLoopRampsConfigs.TorqueOpenLoopRampPeriod = rampRate; - openLoopRampsConfigs.VoltageOpenLoopRampPeriod = rampRate; + /** + * Modifies this configuration's open and closed loop ramp periods for the following control + * types: + * + * + * + *
+ * + * @param rampRateSeconds Time for the motor to reach peak output from 0 + * @return Itself for easy method chaining + */ + public TalonFXConfig withRampRate(Time rampRate) { + closedLoopRampsConfigs.withDutyCycleClosedLoopRampPeriod(rampRate); + closedLoopRampsConfigs.withTorqueClosedLoopRampPeriod(rampRate); + closedLoopRampsConfigs.withVoltageClosedLoopRampPeriod(rampRate); + + openLoopRampsConfigs.withDutyCycleOpenLoopRampPeriod(rampRate); + openLoopRampsConfigs.withTorqueOpenLoopRampPeriod(rampRate); + openLoopRampsConfigs.withVoltageOpenLoopRampPeriod(rampRate); configuration.withClosedLoopRamps(closedLoopRampsConfigs); configuration.withOpenLoopRamps(openLoopRampsConfigs); @@ -283,19 +343,62 @@ public TalonFXConfig withRampRate(double rampRate) { } // CURRENT LIMIT CONFIGS + /** + * Modifies this configuration's supply current lower limit. + * + * @param currentLowerLimit The amount of supply current in amperes allowed after the + * regular {@link CurrentLimitsConfigs#SupplyCurrentLimit} is active for longer than the + * time parameter. + * @param time The amount of time in seconds that the regular {@link + * CurrentLimitsConfigs#SupplyCurrentLimit} can be active before lowring it to the + * currentLowerLimit parameter. + * @return + */ + public TalonFXConfig withLowerLimitSupplyCurrent( + double currentLowerLimitAmps, double timeSeconds) { + return this.withLowerLimitSupplyCurrent( + Amps.of(currentLowerLimitAmps), Seconds.of(timeSeconds)); + } - public TalonFXConfig withLowerLimitSupplyCurrent(double currentLowerLimitAmps, double time) { - currentLimitsConfigs.SupplyCurrentLowerLimit = currentLowerLimitAmps; - currentLimitsConfigs.SupplyCurrentLowerTime = time; + /** + * Modifies this configuration's supply current lower limit. + * + * @param currentLowerLimit The amount of supply current allowed after the regular {@link + * CurrentLimitsConfigs#SupplyCurrentLimit} is active for longer than the time + * parameter. + * @param time The amount of time that the regular {@link + * CurrentLimitsConfigs#SupplyCurrentLimit} can be active before lowring it to the + * currentLowerLimit parameter. + * @return + */ + public TalonFXConfig withLowerLimitSupplyCurrent(Current currentLowerLimit, Time time) { + currentLimitsConfigs.withSupplyCurrentLowerLimit(currentLowerLimit); + currentLimitsConfigs.withSupplyCurrentLowerTime(time); configuration.withCurrentLimits(currentLimitsConfigs); return this; } - public TalonFXConfig withSupplyCurrentLimitAmps(double currentLimitAmps) { - currentLimitsConfigs.SupplyCurrentLimit = currentLimitAmps; - currentLimitsConfigs.SupplyCurrentLimitEnable = true; + /** + * Modifies this configuration's supply current limit and enables it. + * + * @param currentLimit Maximum allowed current in amperes drawn from the battery. + * @return Itself for easier method-chaining. + */ + public TalonFXConfig withSupplyCurrentLimit(double currentLimitAmps) { + return this.withSupplyCurrentLimit(Amps.of(currentLimitAmps)); + } + + /** + * Modifies this configuration's supply current limit and enables it. + * + * @param currentLimit Maximum allowed current drawn from the battery. + * @return Itself for easier method-chaining. + */ + public TalonFXConfig withSupplyCurrentLimit(Current currentLimit) { + currentLimitsConfigs.withSupplyCurrentLimit(currentLimit); + currentLimitsConfigs.withSupplyCurrentLimitEnable(true); configuration.withCurrentLimits(currentLimitsConfigs); @@ -303,16 +406,33 @@ public TalonFXConfig withSupplyCurrentLimitAmps(double currentLimitAmps) { } public TalonFXConfig withSupplyCurrentLimitEnabled(boolean enabled) { - currentLimitsConfigs.SupplyCurrentLimitEnable = enabled; + currentLimitsConfigs.withSupplyCurrentLimitEnable(enabled); configuration.withCurrentLimits(currentLimitsConfigs); return this; } - public TalonFXConfig withStatorCurrentLimitAmps(double currentLimitAmps) { - currentLimitsConfigs.StatorCurrentLimit = currentLimitAmps; - currentLimitsConfigs.StatorCurrentLimitEnable = true; + /** + * Modifies this configuration's stator current limit and enables it. + * + * @param currentLimit Amount of current in amperes allowed in the motor (motoring and regen + * current). + * @return Itself for easier method chaining. + */ + public TalonFXConfig withStatorCurrentLimit(double currentLimitAmps) { + return this.withStatorCurrentLimit(Amps.of(currentLimitAmps)); + } + + /** + * Modifies this configuration's stator current limit and enables it. + * + * @param currentLimit Amount of current allowed in the motor (motoring and regen current). + * @return Itself for easier method chaining. + */ + public TalonFXConfig withStatorCurrentLimit(Current currentLimit) { + currentLimitsConfigs.withStatorCurrentLimit(currentLimit); + currentLimitsConfigs.withStatorCurrentLimitEnable(true); configuration.withCurrentLimits(currentLimitsConfigs); @@ -320,17 +440,50 @@ public TalonFXConfig withStatorCurrentLimitAmps(double currentLimitAmps) { } public TalonFXConfig withStatorCurrentLimitEnabled(boolean enabled) { - currentLimitsConfigs.StatorCurrentLimitEnable = enabled; + currentLimitsConfigs.withStatorCurrentLimitEnable(enabled); configuration.withCurrentLimits(currentLimitsConfigs); return this; } - public TalonFXConfig withTorqueCurrentLimits(double peakForwardTorqueCurrent, double peakReverseTorqueCurrent, double neutralTolerance) { - torqueCurrentConfigs.PeakForwardTorqueCurrent = peakForwardTorqueCurrent; - torqueCurrentConfigs.PeakReverseTorqueCurrent = peakReverseTorqueCurrent; - torqueCurrentConfigs.TorqueNeutralDeadband = neutralTolerance; + /** + * Modifies this configuration's torque current limits. Limits apply during torque current + * control modes. + * + * @param peakForwardTorqueCurrent Maximum forward torque current output in amperes. + * @param peakReverseTorqueCurrent Maximum reverse torque current output in amperes. + * @param neutralTolerance Current range in amperes where requested torque current will + * result in zero bridge output. + * @return Itself for easier method-chaining. + */ + public TalonFXConfig withTorqueCurrentLimits( + double peakForwardTorqueCurrentAmps, + double peakReverseTorqueCurrentAmps, + double neutralToleranceAmps) { + return this.withTorqueCurrentLimits( + Amps.of(peakForwardTorqueCurrentAmps), + Amps.of(peakReverseTorqueCurrentAmps), + Amps.of(neutralToleranceAmps)); + } + + /** + * Modifies this configuration's torque current limits. Limits apply during torque current + * control modes. + * + * @param peakForwardTorqueCurrent Maximum forward torque current output. + * @param peakReverseTorqueCurrent Maximum reverse torque current output. + * @param neutralTolerance Current range where requested torque current will result in zero + * bridge output. + * @return Itself for easier method-chaining. + */ + public TalonFXConfig withTorqueCurrentLimits( + Current peakForwardTorqueCurrent, + Current peakReverseTorqueCurrent, + Current neutralTolerance) { + torqueCurrentConfigs.withPeakForwardTorqueCurrent(peakForwardTorqueCurrent); + torqueCurrentConfigs.withPeakReverseTorqueCurrent(peakReverseTorqueCurrent); + torqueCurrentConfigs.withTorqueNeutralDeadband(neutralTolerance); configuration.withTorqueCurrent(torqueCurrentConfigs); @@ -339,9 +492,28 @@ public TalonFXConfig withTorqueCurrentLimits(double peakForwardTorqueCurrent, do // VOLTAGE LIMIT CONFIGS - public TalonFXConfig withVoltageLimits(double peakForwardVoltage, double peakReverseVoltage) { - voltageConfigs.PeakForwardVoltage = peakForwardVoltage; - voltageConfigs.PeakReverseVoltage = peakReverseVoltage; + /** + * Modifies this configuration's voltage limits. Limits apply during voltage control modes. + * + * @param peakForwardVoltage Maximum forward voltage output in volts. + * @param peakReverseVoltage Maximum reverse voltage output in volts. + * @return Itself for easier method chaining. + */ + public TalonFXConfig withVoltageLimits(double peakForwardVolts, double peakReverseVolts) { + return this.withVoltageLimits(Volts.of(peakForwardVolts), Volts.of(peakReverseVolts)); + } + + /** + * Modifies this configuration's voltage limits. Limits apply during voltage control modes. + * + * @param peakForwardVoltage Maximum forward voltage output. + * @param peakReverseVoltage Maximum reverse voltage output. + * @return Itself for easier method chaining. + */ + public TalonFXConfig withVoltageLimits( + Voltage peakForwardVoltage, Voltage peakReverseVoltage) { + voltageConfigs.withPeakForwardVoltage(peakForwardVoltage); + voltageConfigs.withPeakReverseVoltage(peakReverseVoltage); configuration.withVoltage(voltageConfigs); @@ -349,12 +521,51 @@ public TalonFXConfig withVoltageLimits(double peakForwardVoltage, double peakRev } // SOFTWARE LIMIT CONFIGS + /** + * Modifies this configuration's software limit switch. + * + * @param forwardEnable Whether to set the motor output to neutral if its position exceeds + * the forward threshold. + * @param reverseEnable Whether to set the motor output to neutral if its position exceeds + * the reverse threshold. + * @param forwardThreshold The threshold angle in rotations for the application of the + * forward limit. + * @param reverseThreshold The threshold angle in rotations for the application of the + * reverse limit. + * @return Itself for easier method-chaining. + */ + public TalonFXConfig withSoftLimits( + boolean forwardEnable, + boolean reverseEnable, + double forwardThresholdRotations, + double reverseThresholdRotations) { + return this.withSoftLimits( + forwardEnable, + reverseEnable, + Rotations.of(forwardThresholdRotations), + Rotations.of(reverseThresholdRotations)); + } - public TalonFXConfig withSoftLimits(boolean forwardEnable, boolean reverseEnable, double forwardThreshold, double reverseThreshold) { - softwareLimitSwitchConfigs.ForwardSoftLimitEnable = forwardEnable; - softwareLimitSwitchConfigs.ReverseSoftLimitEnable = reverseEnable; - softwareLimitSwitchConfigs.ForwardSoftLimitThreshold = forwardThreshold; - softwareLimitSwitchConfigs.ReverseSoftLimitThreshold = reverseThreshold; + /** + * Modifies this configuration's software limit switch. + * + * @param forwardEnable Whether to set the motor output to neutral if its position exceeds + * the forward threshold. + * @param reverseEnable Whether to set the motor output to neutral if its position exceeds + * the reverse threshold. + * @param forwardThreshold The threshold angle for the application of the forward limit. + * @param reverseThreshold The threshold angle for the application of the reverse limit. + * @return Itself for easier method-chaining. + */ + public TalonFXConfig withSoftLimits( + boolean forwardEnable, + boolean reverseEnable, + Angle forwardThreshold, + Angle reverseThreshold) { + softwareLimitSwitchConfigs.withForwardSoftLimitEnable(forwardEnable); + softwareLimitSwitchConfigs.withReverseSoftLimitEnable(reverseEnable); + softwareLimitSwitchConfigs.withForwardSoftLimitThreshold(forwardThreshold); + softwareLimitSwitchConfigs.withReverseSoftLimitThreshold(reverseThreshold); configuration.withSoftwareLimitSwitch(softwareLimitSwitchConfigs); @@ -362,10 +573,32 @@ public TalonFXConfig withSoftLimits(boolean forwardEnable, boolean reverseEnable } // MOTION MAGIC CONFIGS + /** + * Modifies this configuration's motion magic profile. + * + * @param maxVelocity Maximum/cruise velocity of the motion profile in rotations per second. + * @param maxAcceleration Maximum acceleration of the motion profile in rotations per second + * squared. + * @return Itself for method-chaining. + */ + public TalonFXConfig withMotionProfile( + double maxVelocityRotPerSec, double maxAccelerationRotPerSecSquared) { + return this.withMotionProfile( + RotationsPerSecond.of(maxVelocityRotPerSec), + RotationsPerSecondPerSecond.of(maxAccelerationRotPerSecSquared)); + } - public TalonFXConfig withMotionProfile(double maxVelocity, double maxAcceleration) { - motionMagicConfigs.MotionMagicCruiseVelocity = maxVelocity; - motionMagicConfigs.MotionMagicAcceleration = maxAcceleration; + /** + * Modifies this configuration's motion magic profile. + * + * @param maxVelocity Maximum/cruise velocity of the motion profile. + * @param maxAcceleration Maximum acceleration of the motion profile. + * @return Itself for method-chaining. + */ + public TalonFXConfig withMotionProfile( + AngularVelocity maxVelocity, AngularAcceleration maxAcceleration) { + motionMagicConfigs.withMotionMagicCruiseVelocity(maxVelocity); + motionMagicConfigs.withMotionMagicAcceleration(maxAcceleration); configuration.withMotionMagic(motionMagicConfigs); @@ -376,9 +609,9 @@ public TalonFXConfig withMotionProfile(double maxVelocity, double maxAcceleratio public TalonFXConfig withRemoteSensor( int ID, FeedbackSensorSourceValue source, double rotorToSensorRatio) { - feedbackConfigs.FeedbackRemoteSensorID = ID; - feedbackConfigs.FeedbackSensorSource = source; - feedbackConfigs.RotorToSensorRatio = rotorToSensorRatio; + feedbackConfigs.withFeedbackRemoteSensorID(ID); + feedbackConfigs.withFeedbackSensorSource(source); + feedbackConfigs.withRotorToSensorRatio(rotorToSensorRatio); configuration.withFeedback(feedbackConfigs); @@ -386,7 +619,7 @@ public TalonFXConfig withRemoteSensor( } public TalonFXConfig withSensorToMechanismRatio(double sensorToMechanismRatio) { - feedbackConfigs.SensorToMechanismRatio = sensorToMechanismRatio; + feedbackConfigs.withSensorToMechanismRatio(sensorToMechanismRatio); configuration.withFeedback(feedbackConfigs); diff --git a/src/main/java/com/stuypulse/robot/constants/Ports.java b/src/main/java/com/stuypulse/robot/constants/Ports.java index 1a2106d..d987ea2 100644 --- a/src/main/java/com/stuypulse/robot/constants/Ports.java +++ b/src/main/java/com/stuypulse/robot/constants/Ports.java @@ -1,8 +1,7 @@ /************************ PROJECT PHIL ************************/ -/* Copyright (c) 2024 StuyPulse Robotics. All rights reserved.*/ +/* Copyright (c) 2026 StuyPulse Robotics. All rights reserved.*/ /* This work is licensed under the terms of the MIT license. */ /**************************************************************/ - package com.stuypulse.robot.constants; /** This file contains the different ports of motors, solenoids and sensors */ diff --git a/src/main/java/com/stuypulse/robot/constants/Settings.java b/src/main/java/com/stuypulse/robot/constants/Settings.java index a1b4525..427c5b2 100644 --- a/src/main/java/com/stuypulse/robot/constants/Settings.java +++ b/src/main/java/com/stuypulse/robot/constants/Settings.java @@ -1,15 +1,13 @@ /************************ PROJECT PHIL ************************/ -/* Copyright (c) 2024 StuyPulse Robotics. All rights reserved.*/ +/* Copyright (c) 2026 StuyPulse Robotics. All rights reserved.*/ /* This work is licensed under the terms of the MIT license. */ /**************************************************************/ - package com.stuypulse.robot.constants; - -/*- +/** * File containing tunable settings for every subsystem on the robot. * - * We use DogLog's tunables in order to have tunable - * values that we can edit on Shuffleboard. + * We use DogLog's tunables in order to have tunable values that we can edit from external + * dashboards. */ public interface Settings {} diff --git a/vendordeps/AdvantageKit.json b/vendordeps/AdvantageKit.json new file mode 100644 index 0000000..0573d11 --- /dev/null +++ b/vendordeps/AdvantageKit.json @@ -0,0 +1,35 @@ +{ + "fileName": "AdvantageKit.json", + "name": "AdvantageKit", + "version": "27.0.0-alpha-4", + "uuid": "d820cc26-74e3-11ec-90d6-0242ac120003", + "wpilibYear": "2027_alpha5", + "mavenUrls": [ + "https://frcmaven.wpi.org/artifactory/littletonrobotics-mvn-release/" + ], + "jsonUrl": "https://github.com/Mechanical-Advantage/AdvantageKit/releases/latest/download/AdvantageKit.json", + "javaDependencies": [ + { + "groupId": "org.littletonrobotics.akit", + "artifactId": "akit-java", + "version": "27.0.0-alpha-4" + } + ], + "jniDependencies": [ + { + "groupId": "org.littletonrobotics.akit", + "artifactId": "akit-wpilibio", + "version": "27.0.0-alpha-4", + "skipInvalidPlatforms": false, + "isJar": false, + "validPlatforms": [ + "linuxsystemcore", + "linuxx86-64", + "linuxarm64", + "osxuniversal", + "windowsx86-64" + ] + } + ], + "cppDependencies": [] +} \ No newline at end of file diff --git a/vendordeps/CommandsV3.json b/vendordeps/CommandsV3.json new file mode 100644 index 0000000..cf494f9 --- /dev/null +++ b/vendordeps/CommandsV3.json @@ -0,0 +1,25 @@ +{ + "fileName": "CommandsV3.json", + "name": "Commands v3", + "version": "1.0.0", + "uuid": "4decdc05-a056-46cf-9561-39449bbb0130", + "wpilibYear": "2027_alpha5", + "mavenUrls": [], + "jsonUrl": "", + "conflictsWith": [ + { + "uuid": "111e20f7-815e-48f8-9dd6-e675ce75b266", + "errorMessage": "Users can not have both Commands v2 and Commands v3 vendordeps in their robot program.", + "offlineFileName": "CommandsV2.json" + } + ], + "javaDependencies": [ + { + "groupId": "org.wpilib", + "artifactId": "commands3-java", + "version": "wpilib" + } + ], + "jniDependencies": [], + "cppDependencies": [] +} \ No newline at end of file diff --git a/vendordeps/DogLog.json b/vendordeps/DogLog.json index 7201ed0..608dc30 100644 --- a/vendordeps/DogLog.json +++ b/vendordeps/DogLog.json @@ -3,11 +3,11 @@ { "groupId": "com.github.jonahsnider", "artifactId": "doglog", - "version": "2026.5.0" + "version": "2027.1.0" } ], "fileName": "DogLog.json", - "frcYear": "2026", + "wpilibYear": "2027_alpha5", "jsonUrl": "https://doglog.dev/vendordep.json", "name": "DogLog", "jniDependencies": [], @@ -15,6 +15,6 @@ "https://jitpack.io" ], "cppDependencies": [], - "version": "2026.5.0", + "version": "2027.1.0", "uuid": "65592ce1-2251-4a31-8e4b-2df20dacebe4" } \ No newline at end of file diff --git a/vendordeps/PathplannerLib.json b/vendordeps/PathplannerLib.json deleted file mode 100644 index 4414707..0000000 --- a/vendordeps/PathplannerLib.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "fileName": "PathplannerLib.json", - "name": "PathplannerLib", - "version": "2026.1.2", - "uuid": "1b42324f-17c6-4875-8e77-1c312bc8c786", - "frcYear": "2026", - "mavenUrls": [ - "https://3015rangerrobotics.github.io/pathplannerlib/repo" - ], - "jsonUrl": "https://3015rangerrobotics.github.io/pathplannerlib/PathplannerLib.json", - "javaDependencies": [ - { - "groupId": "com.pathplanner.lib", - "artifactId": "PathplannerLib-java", - "version": "2026.1.2" - } - ], - "jniDependencies": [], - "cppDependencies": [ - { - "groupId": "com.pathplanner.lib", - "artifactId": "PathplannerLib-cpp", - "version": "2026.1.2", - "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-frc2026-latest.json b/vendordeps/Phoenix6-26.50.0-alpha-1.json similarity index 87% rename from vendordeps/Phoenix6-frc2026-latest.json rename to vendordeps/Phoenix6-26.50.0-alpha-1.json index 3aa7b02..f7db60a 100644 --- a/vendordeps/Phoenix6-frc2026-latest.json +++ b/vendordeps/Phoenix6-26.50.0-alpha-1.json @@ -1,60 +1,60 @@ { - "fileName": "Phoenix6-frc2026-latest.json", + "fileName": "Phoenix6-26.50.0-alpha-1.json", "name": "CTRE-Phoenix (v6)", - "version": "26.3.0", - "frcYear": "2026", + "version": "26.50.0-alpha-1", + "wpilibYear": "2027_alpha5", "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-frc2026-latest.json", + "jsonUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix6/latest/Phoenix6-frc2027-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-frc2026-latest.json" + "errorMessage": "Users cannot have both the replay and regular Phoenix 6 vendordeps in their robot program.", + "offlineFileName": "Phoenix6-replay-frc2027-latest.json" } ], "javaDependencies": [ { "groupId": "com.ctre.phoenix6", "artifactId": "wpiapi-java", - "version": "26.3.0" + "version": "26.50.0-alpha-1" } ], "jniDependencies": [ { "groupId": "com.ctre.phoenix6", "artifactId": "api-cpp", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ "windowsx86-64", "linuxx86-64", "linuxarm64", - "linuxathena" + "linuxsystemcore" ], "simMode": "hwsim" }, { "groupId": "com.ctre.phoenix6", "artifactId": "tools", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ "windowsx86-64", "linuxx86-64", "linuxarm64", - "linuxathena" + "linuxsystemcore" ], "simMode": "hwsim" }, { "groupId": "com.ctre.phoenix6.sim", "artifactId": "api-cpp-sim", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -68,7 +68,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "tools-sim", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -82,7 +82,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simTalonSRX", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -96,7 +96,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simVictorSPX", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -110,7 +110,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simPigeonIMU", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -124,7 +124,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProTalonFX", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -138,7 +138,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProTalonFXS", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -152,7 +152,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANcoder", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -166,7 +166,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProPigeon2", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -180,7 +180,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANrange", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -194,7 +194,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANdi", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -208,7 +208,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANdle", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -224,7 +224,7 @@ { "groupId": "com.ctre.phoenix6", "artifactId": "wpiapi-cpp", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "libName": "CTRE_Phoenix6_WPI", "headerClassifier": "headers", "sharedLibrary": true, @@ -233,14 +233,14 @@ "windowsx86-64", "linuxx86-64", "linuxarm64", - "linuxathena" + "linuxsystemcore" ], "simMode": "hwsim" }, { "groupId": "com.ctre.phoenix6", "artifactId": "tools", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "libName": "CTRE_PhoenixTools", "headerClassifier": "headers", "sharedLibrary": true, @@ -249,14 +249,14 @@ "windowsx86-64", "linuxx86-64", "linuxarm64", - "linuxathena" + "linuxsystemcore" ], "simMode": "hwsim" }, { "groupId": "com.ctre.phoenix6.sim", "artifactId": "wpiapi-cpp-sim", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "libName": "CTRE_Phoenix6_WPISim", "headerClassifier": "headers", "sharedLibrary": true, @@ -272,7 +272,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "tools-sim", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "libName": "CTRE_PhoenixTools_Sim", "headerClassifier": "headers", "sharedLibrary": true, @@ -288,7 +288,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simTalonSRX", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "libName": "CTRE_SimTalonSRX", "headerClassifier": "headers", "sharedLibrary": true, @@ -304,7 +304,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simVictorSPX", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "libName": "CTRE_SimVictorSPX", "headerClassifier": "headers", "sharedLibrary": true, @@ -320,7 +320,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simPigeonIMU", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "libName": "CTRE_SimPigeonIMU", "headerClassifier": "headers", "sharedLibrary": true, @@ -336,7 +336,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProTalonFX", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "libName": "CTRE_SimProTalonFX", "headerClassifier": "headers", "sharedLibrary": true, @@ -352,7 +352,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProTalonFXS", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "libName": "CTRE_SimProTalonFXS", "headerClassifier": "headers", "sharedLibrary": true, @@ -368,7 +368,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANcoder", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "libName": "CTRE_SimProCANcoder", "headerClassifier": "headers", "sharedLibrary": true, @@ -384,7 +384,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProPigeon2", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "libName": "CTRE_SimProPigeon2", "headerClassifier": "headers", "sharedLibrary": true, @@ -400,7 +400,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANrange", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "libName": "CTRE_SimProCANrange", "headerClassifier": "headers", "sharedLibrary": true, @@ -416,7 +416,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANdi", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "libName": "CTRE_SimProCANdi", "headerClassifier": "headers", "sharedLibrary": true, @@ -432,7 +432,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANdle", - "version": "26.3.0", + "version": "26.50.0-alpha-1", "libName": "CTRE_SimProCANdle", "headerClassifier": "headers", "sharedLibrary": true, diff --git a/vendordeps/WPILibNewCommands.json b/vendordeps/WPILibNewCommands.json deleted file mode 100644 index 9fae080..0000000 --- a/vendordeps/WPILibNewCommands.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "fileName": "WPILibNewCommands.json", - "name": "WPILib-New-Commands", - "version": "1.0.0", - "uuid": "111e20f7-815e-48f8-9dd6-e675ce75b266", - "frcYear": "2026", - "mavenUrls": [], - "jsonUrl": "", - "javaDependencies": [ - { - "groupId": "edu.wpi.first.wpilibNewCommands", - "artifactId": "wpilibNewCommands-java", - "version": "wpilib" - } - ], - "jniDependencies": [], - "cppDependencies": [ - { - "groupId": "edu.wpi.first.wpilibNewCommands", - "artifactId": "wpilibNewCommands-cpp", - "version": "wpilib", - "libName": "wpilibNewCommands", - "headerClassifier": "headers", - "sourcesClassifier": "sources", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "linuxathena", - "linuxarm32", - "linuxarm64", - "windowsx86-64", - "windowsx86", - "linuxx86-64", - "osxuniversal" - ] - } - ] - } - \ No newline at end of file