From 049c290eea59f52bbdc42fc77b515c2e416295dd Mon Sep 17 00:00:00 2001 From: Theta Back Date: Sun, 6 Sep 2026 17:56:23 -0400 Subject: [PATCH 01/20] (#1) Updated to wpilib 27 alpha in order to build --- .gitignore | 10 +- .vscode/launch.json | 8 +- .vscode/settings.json | 15 +- .wpilib/wpilib_preferences.json | 10 +- WPILib-License.md | 19 +- build.gradle | 209 ++------ gradle/wrapper/gradle-wrapper.jar | Bin 43583 -> 48966 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 15 +- gradlew.bat | 25 +- settings.gradle | 18 +- src/main/java/first/Main.java | 25 + src/main/java/frc/robot/Constants.java | 2 +- .../java/frc/robot/CoordinationLayer.java | 104 ++-- .../frc/robot/DependencyOrderedExecutor.java | 10 +- src/main/java/frc/robot/InitSubsystems.java | 4 +- src/main/java/frc/robot/Main.java | 5 +- src/main/java/frc/robot/Robot.java | 51 +- src/main/java/frc/robot/RobotContainer.java | 41 +- src/main/java/frc/robot/ShotCalculations.java | 45 +- src/main/java/frc/robot/auto/Auto.java | 2 +- src/main/java/frc/robot/auto/AutoAction.java | 2 +- src/main/java/frc/robot/auto/Autos.java | 8 +- .../coordinationLayer/ClimbHangAction.java | 4 +- .../coordinationLayer/ClimbSearchAction.java | 2 +- .../coordinationLayer/DeployIntakeAction.java | 4 +- .../auto/coordinationLayer/StartShooting.java | 4 +- .../auto/coordinationLayer/StopShooting.java | 4 +- .../coordinationLayer/StowIntakeAction.java | 4 +- .../frc/robot/auto/drive/AutoPilotAction.java | 4 +- .../auto/drive/FollowPathPlannerPath.java | 6 +- .../frc/robot/auto/drive/StopDriveAction.java | 2 +- .../auto/drive/XBasedAutoPilotAction.java | 2 +- .../frc/robot/auto/general/AutoReference.java | 2 +- .../java/frc/robot/auto/general/Deadline.java | 2 +- .../auto/general/NetworkConfigurableWait.java | 10 +- .../java/frc/robot/auto/general/Parallel.java | 4 +- .../java/frc/robot/auto/general/Print.java | 4 +- .../java/frc/robot/auto/general/Race.java | 4 +- .../java/frc/robot/auto/general/Sequence.java | 4 +- .../java/frc/robot/auto/general/Wait.java | 6 +- src/main/java/frc/robot/autogen/Dsl.java | 20 +- src/main/java/frc/robot/autogen/Field.java | 10 +- .../java/frc/robot/autogen/GenerateAutos.java | 4 +- .../frc/robot/commands/DriveCommands.java | 54 +-- .../AllianceBasedFieldConstants.java | 16 +- .../robot/constants/AprilTagConstants.java | 4 +- .../frc/robot/constants/ClimberConstants.java | 40 +- .../frc/robot/constants/FieldConstants.java | 8 +- .../constants/FieldLocationInstance.java | 2 +- .../frc/robot/constants/FieldLocations.java | 2 +- .../frc/robot/constants/HoodConstants.java | 44 +- .../frc/robot/constants/HopperConstants.java | 42 +- .../frc/robot/constants/IndexerConstants.java | 36 +- .../frc/robot/constants/IntakeConstants.java | 52 +- .../frc/robot/constants/JsonConstants.java | 18 +- .../robot/constants/ManualModeConstants.java | 6 +- .../java/frc/robot/constants/RobotInfo.java | 22 +- .../frc/robot/constants/ShooterConstants.java | 40 +- .../java/frc/robot/constants/ShotMaps.java | 26 +- .../robot/constants/StrategyConstants.java | 4 +- .../constants/TransferRollerConstants.java | 36 +- .../frc/robot/constants/TurretConstants.java | 32 +- .../frc/robot/constants/VisionConstants.java | 10 +- .../robot/constants/drive/DriveConstants.java | 24 +- .../robot/constants/drive/ModuleConfig.java | 4 +- .../drive/PhysicalDriveConstants.java | 22 +- .../frc/robot/coordination/MatchState.java | 39 +- .../frc/robot/generated/TunerConstants.java | 10 +- .../subsystems/climber/ClimberState.java | 4 +- .../subsystems/climber/ClimberSubsystem.java | 43 +- .../frc/robot/subsystems/drive/Drive.java | 133 +++--- .../subsystems/drive/DriveCoordinator.java | 14 +- .../drive/DriveCoordinatorCommands.java | 14 +- .../frc/robot/subsystems/drive/GyroIO.java | 2 +- .../robot/subsystems/drive/GyroIONavX.java | 4 +- .../robot/subsystems/drive/GyroIOPigeon2.java | 8 +- .../frc/robot/subsystems/drive/Module.java | 34 +- .../frc/robot/subsystems/drive/ModuleIO.java | 4 +- .../robot/subsystems/drive/ModuleIOSim.java | 43 +- .../subsystems/drive/ModuleIOTalonFX.java | 14 +- .../subsystems/drive/ModuleIOTalonFXS.java | 14 +- .../drive/PhoenixOdometryThread.java | 6 +- .../frc/robot/subsystems/hood/HoodState.java | 4 +- .../robot/subsystems/hood/HoodSubsystem.java | 50 +- .../subsystems/hopper/HopperSubsystem.java | 28 +- .../subsystems/indexer/IndexerSubsystem.java | 18 +- .../robot/subsystems/intake/IntakeState.java | 8 +- .../subsystems/intake/IntakeSubsystem.java | 30 +- .../subsystems/shooter/ShooterSubsystem.java | 41 +- .../TransferRollerSubsystem.java | 22 +- .../robot/subsystems/turret/TurretState.java | 6 +- .../subsystems/turret/TurretSubsystem.java | 70 +-- .../java/frc/robot/util/CommandState.java | 2 +- src/main/java/frc/robot/util/Elastic.java | 33 +- .../java/frc/robot/util/LocalADStarAK.java | 4 +- .../frc/robot/util/json/JSONAPTarget.java | 6 +- .../util/json/JSONMotionProfileConfig.java | 14 +- .../robot/util/littletonUtil/GeomUtil.java | 28 +- .../util/littletonUtil/PoseEstimator.java | 26 +- vendordeps/AdvantageKit.json | 68 +-- vendordeps/Autopilot.json | 20 - vendordeps/CommandsV2.json | 46 ++ vendordeps/PathplannerLib.json | 38 -- vendordeps/PathplannerLibSystemCoreAlpha.json | 37 ++ vendordeps/Phoenix6-26.1.2.json | 449 ------------------ vendordeps/Phoenix6-26.50.0-alpha-1.json | 449 ++++++++++++++++++ vendordeps/REVLib.json | 257 +++++----- vendordeps/WPILibNewCommands.json | 38 -- vendordeps/photonlib.json | 140 +++--- 110 files changed, 1729 insertions(+), 1869 deletions(-) create mode 100644 src/main/java/first/Main.java delete mode 100644 vendordeps/Autopilot.json create mode 100644 vendordeps/CommandsV2.json delete mode 100644 vendordeps/PathplannerLib.json create mode 100644 vendordeps/PathplannerLibSystemCoreAlpha.json delete mode 100644 vendordeps/Phoenix6-26.1.2.json create mode 100644 vendordeps/Phoenix6-26.50.0-alpha-1.json delete mode 100644 vendordeps/WPILibNewCommands.json diff --git a/.gitignore b/.gitignore index 38a40cca..34cbaac1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,6 @@ # This gitignore has been specially created by the WPILib team. # If you remove items from this file, intellisense might break. -### Python ### -__pycache__/ -*.pyc - ### C++ ### # Prerequisites *.d @@ -174,7 +170,7 @@ out/ # Simulation GUI and other tools window save file networktables.json -simgui*.json +simgui.json *-window.json # Simulation data log directory @@ -187,5 +183,5 @@ ctre_sim/ /.cache compile_commands.json -# Version file -src/main/java/frc/robot/BuildConstants.java \ No newline at end of file +# Eclipse generated file for annotation processors +.factorypath diff --git a/.vscode/launch.json b/.vscode/launch.json index b8c19206..c9c9713d 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,17 +1,21 @@ { + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { "type": "wpilib", "name": "WPILib Desktop Debug", "request": "launch", - "desktop": true + "desktop": true, }, { "type": "wpilib", "name": "WPILib roboRIO Debug", "request": "launch", - "desktop": false + "desktop": false, } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 1e73416d..6ea00dae 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -18,15 +18,12 @@ { "name": "WPIlibUnitTests", "workingDirectory": "${workspaceFolder}/build/jni/release", - "vmargs": [ - "-Djava.library.path=${workspaceFolder}/build/jni/release" - ], + "vmargs": [ "-Djava.library.path=${workspaceFolder}/build/jni/release" ], "env": { - "LD_LIBRARY_PATH": "${workspaceFolder}/build/jni/release", + "LD_LIBRARY_PATH": "${workspaceFolder}/build/jni/release" , "DYLD_LIBRARY_PATH": "${workspaceFolder}/build/jni/release" } }, - null ], "java.test.defaultConfig": "WPIlibUnitTests", "spotlessGradle.format.enable": true, @@ -42,7 +39,7 @@ "org.mockito.Mockito.*", "org.mockito.ArgumentMatchers.*", "org.mockito.Answers.*", - "edu.wpi.first.units.Units.*" + "org.wpilib.units.Units.*" ], "java.completion.filteredTypes": [ "java.awt.*", @@ -58,9 +55,9 @@ "javax.swing.*", "javax.management.*", "javax.smartcardio.*", - "edu.wpi.first.math.proto.*", - "edu.wpi.first.math.**.proto.*", - "edu.wpi.first.math.**.struct.*" + "org.wpilib.math.proto.*", + "org.wpilib.math.**.proto.*", + "org.wpilib.math.**.struct.*", ], "java.dependency.enableDependencyCheckup": false, "editor.defaultFormatter": "richardwillis.vscode-spotless-gradle", diff --git a/.wpilib/wpilib_preferences.json b/.wpilib/wpilib_preferences.json index 9c99fd8c..ad433eca 100644 --- a/.wpilib/wpilib_preferences.json +++ b/.wpilib/wpilib_preferences.json @@ -1,6 +1,6 @@ { - "enableCppIntellisense": false, - "currentLanguage": "java", - "projectYear": "2026", - "teamNumber": 401 -} + "enableCppIntellisense": false, + "currentLanguage": "java", + "projectYear": "2027_alpha5", + "teamNumber": 401 +} \ No newline at end of file diff --git a/WPILib-License.md b/WPILib-License.md index 051080d8..eb3061b0 100644 --- a/WPILib-License.md +++ b/WPILib-License.md @@ -1,17 +1,16 @@ -Copyright (c) 2009-2025 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 modification, are permitted provided that the following conditions are met: - -- Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -- Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -- Neither the name of FIRST, WPILib, nor the names of other WPILib - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of FIRST, WPILib, nor the names of other WPILib + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY FIRST AND OTHER WPILIB CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED diff --git a/build.gradle b/build.gradle index 0c44f574..1e9f37df 100644 --- a/build.gradle +++ b/build.gradle @@ -1,112 +1,78 @@ plugins { id "java" - id "edu.wpi.first.GradleRIO" version "2026.2.1" + id "org.wpilib.GradleRIO" version "2027.0.0-alpha-6" + id "com.gradleup.shadow" version "9.3.0" id "com.peterabeles.gversion" version "1.10" id "com.diffplug.spotless" version "8.1.0" } java { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_25 + targetCompatibility = JavaVersion.VERSION_25 } repositories { + mavenLocal() mavenCentral() - // mavenLocal() } -def ROBOT_MAIN_CLASS = "frc.robot.Main" +def ROBOT_MAIN_CLASS = "first.Main" -// 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')) { - // 422 2025 arguments - // gcType = 'Other' - // jvmArgs.add("-XX:GCTimeRatio=5") - // jvmArgs.add("-XX:+UseG1GC") - // jvmArgs.add("-XX:MaxGCPauseMillis=20") - - // 401 arguments - jvmArgs.add("-XX:+UnlockExperimentalVMOptions") - jvmArgs.add("-XX:GCTimeRatio=5") - jvmArgs.add("-XX:+UseSerialGC") - jvmArgs.add("-XX:MaxGCPauseMillis=20") - - // The options below may improve performance, but should only be enabled on the RIO 2 - // - final MAX_JAVA_HEAP_SIZE_MB = 100; - jvmArgs.add("-Xmx" + MAX_JAVA_HEAP_SIZE_MB + "M") - jvmArgs.add("-Xms" + MAX_JAVA_HEAP_SIZE_MB + "M") - jvmArgs.add("-XX:+AlwaysPreTouch") - - // Enable VisualVM connection - // jvmArgs.add("-Dcom.sun.management.jmxremote=true") - // jvmArgs.add("-Dcom.sun.management.jmxremote.port=1198") - // jvmArgs.add("-Dcom.sun.management.jmxremote.local.only=false") - // jvmArgs.add("-Dcom.sun.management.jmxremote.ssl=false") - // jvmArgs.add("-Dcom.sun.management.jmxremote.authenticate=false") - // jvmArgs.add("-Djava.rmi.server.hostname=10.04.01.2") - - // Cause code hotspots to be compiled after 50 runs rather than the default of 1500 (C1) - // /10000 (C2). This option is potentially ignored anyway when tiered - // compilation is enabled. - // jvmArgs.add("-XX:CompileThreshold=50") + wpilibJava(getArtifactTypeClass('WPILibJavaArtifact')) { } // Static files artifact - frcStaticFileDeploy(getArtifactTypeClass('FileTreeArtifact')) { + wpilibStaticFileDeploy(getArtifactTypeClass('FileTreeArtifact')) { files = project.fileTree('src/main/deploy') - directory = '/home/lvuser/deploy' - // Change to true to delete files on roboRIO that no - // longer exist in deploy directory on roboRIO - deleteOldFiles = true + 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 all targets including JNI, which will drastically impact // performance. wpi.java.debugJni = false // Set this to true to enable desktop support. -def includeDesktopSupport = true - -// Configuration for AdvantageKit -task(replayWatch, type: JavaExec) { - mainClass = "org.littletonrobotics.junction.ReplayWatch" - classpath = sourceSets.main.runtimeClasspath -} +def includeDesktopSupport = false // Defining my dependencies. In this case, WPILib (+ friends), and vendor libraries. -// Also defines JUnit 4. +// 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) @@ -122,9 +88,11 @@ dependencies { def akitJson = new groovy.json.JsonSlurper().parseText(new File(projectDir.getAbsolutePath() + "/vendordeps/AdvantageKit.json").text) annotationProcessor "org.littletonrobotics.akit:akit-autolog:$akitJson.version" - def coppercoreVersion = "2026.2.23" + def coppercoreVersion = "2026.3.1" implementation "com.google.code.gson:gson:2.11.0" + implementation "io.avaje:avaje-jsonb:3.14" + annotationProcessor "io.avaje:avaje-jsonb-generator:3.14" implementation "io.github.team401.coppercore:controls:$coppercoreVersion" implementation "io.github.team401.coppercore:geometry:$coppercoreVersion" @@ -134,6 +102,7 @@ dependencies { implementation "io.github.team401.coppercore:vision:$coppercoreVersion" implementation "io.github.team401.coppercore:wpilib_interface:$coppercoreVersion" implementation "io.github.team401.coppercore:metadata:$coppercoreVersion" + implementation "com.github.therekrab:autopilot:1.7.0-alpha-7" } test { @@ -142,123 +111,27 @@ test { } // Simulation configuration (e.g. environment variables). -// -// The sim GUI is *disabled* by default to support running -// AdvantageKit log replay, which requires that all HAL -// sim extensions be disabled. -wpi.sim.addGui().defaultEnabled = false +wpi.sim.addGui().defaultEnabled = true wpi.sim.addDriverstation() -// 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) - } - } - from sourceSets.main.allSource - manifest edu.wpi.first.gradlerio.GradleRIOPlugin.javaManifest(ROBOT_MAIN_CLASS) +// 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 = jar -wpi.java.configureExecutableTasks(jar) +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' } - -// Create version file -project.compileJava.dependsOn(createVersionFile) -gversion { - srcDir = "src/main/java/" - classPackage = "frc.robot" - className = "BuildConstants" - dateFormat = "yyyy-MM-dd HH:mm:ss z" - timeZone = "America/New_York" - indent = " " -} - -// Create commit with working changes on event branches -task(eventDeploy) { - doLast { - if (project.gradle.startParameter.taskNames.any({ it.toLowerCase().contains("deploy") })) { - def branchPrefix = "2026-" - def branch = 'git branch --show-current'.execute().text.trim() - def commitMessage = "Update at '${new Date().toString()}'" - - if (branch.startsWith(branchPrefix)) { - exec { - workingDir(projectDir) - executable 'git' - args 'add', '-A' - } - exec { - workingDir(projectDir) - executable 'git' - args 'commit', '-m', commitMessage - ignoreExitValue = true - } - - println "Committed to branch: '$branch'" - println "Commit message: '$commitMessage'" - } else { - println "Not on an event branch, skipping commit" - } - } else { - println "Not running deploy task, skipping commit" - } - } -} -createVersionFile.dependsOn(eventDeploy) - -// Spotless formatting -project.compileJava.dependsOn(spotlessApply) -spotless { - java { - // Restrict formatting to files under the workspace 'src' directory. - // Using '.' can sometimes pick up files mounted from other filesystems - // (e.g. WSL mounts) which Spotless rejects. Targeting 'src' keeps the - // formatter inside the project directory. - target fileTree('src') { - include "**/*.java" - exclude "**/build/**", "**/build-*/**", "settings_gui/**" - } - toggleOffOn() - googleJavaFormat() - removeUnusedImports() - trimTrailingWhitespace() - endWithNewline() - } - groovyGradle { - target fileTree(".") { - include "**/*.gradle" - exclude "**/build/**", "**/build-*/**", "settings_gui/**" - } - greclipse() - leadingTabsToSpaces(4) - trimTrailingWhitespace() - endWithNewline() - } - json { - target fileTree(".") { - include "**/*.json" - exclude "**/build/**", "**/build-*/**", "elastic_layouts/*.json", "settings_gui/**", "auto_generator/**", "src/main/deploy/constants/comp/Autos.json" - } - gson().indentWithSpaces(2) - } - format "misc", { - target fileTree(".") { - include "**/*.md", "**/.gitignore" - exclude "**/build/**", "**/build-*/**", "settings_gui/**" - } - trimTrailingWhitespace() - leadingTabsToSpaces(2) - endWithNewline() - } -} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index a4b76b9530d66f5e68d973ea569d8e19de379189..d997cfc60f4cff0e7451d19d49a82fa986695d07 100644 GIT binary patch delta 40682 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Ðt5p(LLtXn?pxm3OZHd|13r);5)1uCW40m{;j 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 A;{X5v delta 35496 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 34bd9ce9..42bb5ac9 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 1aa94a42..739907df 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/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/. @@ -84,7 +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 "${APP_HOME:-./}" > /dev/null && pwd -P ) || 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 @@ -112,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. @@ -170,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" ) @@ -203,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 93e3f59f..c4bdd3ab 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,22 +59,21 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 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 486702ac..e2626a81 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/java/first/Main.java b/src/main/java/first/Main.java new file mode 100644 index 00000000..8fd1dabb --- /dev/null +++ b/src/main/java/first/Main.java @@ -0,0 +1,25 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package first; + +import org.wpilib.framework.RobotBase; + +/** + * Do NOT add any static variables to this class, or any initialization at all. Unless you know what + * you are doing, do not modify this file except to change the parameter class to the startRobot + * call. + */ +public final class Main { + private Main() {} + + /** + * Main initialization function. Do not perform any initialization here. + * + *

If you change your main robot class, change the parameter type. + */ + public static void main(String... args) { + RobotBase.startRobot(frc.robot.Robot.class); + } +} diff --git a/src/main/java/frc/robot/Constants.java b/src/main/java/frc/robot/Constants.java index c7eefb17..12a0e48c 100644 --- a/src/main/java/frc/robot/Constants.java +++ b/src/main/java/frc/robot/Constants.java @@ -7,7 +7,7 @@ package frc.robot; -import edu.wpi.first.wpilibj.RobotBase; +import org.wpilib.framework.RobotBase; /** * This class defines the runtime mode used by AdvantageKit. The mode is always "real" when running diff --git a/src/main/java/frc/robot/CoordinationLayer.java b/src/main/java/frc/robot/CoordinationLayer.java index 5c27951c..855be4a4 100644 --- a/src/main/java/frc/robot/CoordinationLayer.java +++ b/src/main/java/frc/robot/CoordinationLayer.java @@ -1,12 +1,12 @@ package frc.robot; -import static edu.wpi.first.units.Units.Degrees; -import static edu.wpi.first.units.Units.Meters; -import static edu.wpi.first.units.Units.MetersPerSecond; -import static edu.wpi.first.units.Units.RPM; -import static edu.wpi.first.units.Units.Radians; -import static edu.wpi.first.units.Units.RadiansPerSecond; -import static edu.wpi.first.units.Units.Seconds; +import static org.wpilib.units.Units.Degrees; +import static org.wpilib.units.Units.Meters; +import static org.wpilib.units.Units.MetersPerSecond; +import static org.wpilib.units.Units.RPM; +import static org.wpilib.units.Units.Radians; +import static org.wpilib.units.Units.RadiansPerSecond; +import static org.wpilib.units.Units.Seconds; import coppercore.geometry.EnhancedLine2d; import coppercore.geometry.Rectangle; @@ -19,27 +19,25 @@ import coppercore.wpilib_interface.controllers.Controller.Button; import coppercore.wpilib_interface.controllers.Controllers; import coppercore.wpilib_interface.tuning.TestModeManager; -import edu.wpi.first.math.MathUtil; -import edu.wpi.first.math.Vector; -import edu.wpi.first.math.filter.Debouncer; -import edu.wpi.first.math.filter.Debouncer.DebounceType; -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.Rotation3d; -import edu.wpi.first.math.geometry.Translation2d; -import edu.wpi.first.math.geometry.Translation3d; -import edu.wpi.first.math.kinematics.ChassisSpeeds; -import edu.wpi.first.math.numbers.N3; -import edu.wpi.first.math.util.Units; -import edu.wpi.first.units.measure.Time; -import edu.wpi.first.wpilibj.Alert; -import edu.wpi.first.wpilibj.Alert.AlertType; -import edu.wpi.first.wpilibj.DriverStation; -import edu.wpi.first.wpilibj.RobotController; -import edu.wpi.first.wpilibj.event.EventLoop; -import edu.wpi.first.wpilibj2.command.InstantCommand; -import edu.wpi.first.wpilibj2.command.button.Trigger; +import org.wpilib.math.linalg.Vector; +import org.wpilib.math.filter.Debouncer; +import org.wpilib.math.filter.Debouncer.DebounceType; +import org.wpilib.math.geometry.Pose2d; +import org.wpilib.math.geometry.Pose3d; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.math.geometry.Rotation3d; +import org.wpilib.math.geometry.Translation2d; +import org.wpilib.math.geometry.Translation3d; +import org.wpilib.math.kinematics.ChassisVelocities; +import org.wpilib.math.numbers.N3; +import org.wpilib.math.util.Units; +import org.wpilib.units.measure.Time; +import org.wpilib.driverstation.Alert; +import org.wpilib.driverstation.internal.DriverStationBackend; +import org.wpilib.system.RobotController; +import org.wpilib.event.EventLoop; +import org.wpilib.command2.InstantCommand; +import org.wpilib.command2.button.Trigger; import frc.robot.DependencyOrderedExecutor.ActionKey; import frc.robot.ShotCalculations.MapBasedShotInfo; import frc.robot.ShotCalculations.ShotInfo; @@ -220,10 +218,10 @@ public enum PassGoalZone { // Logging private final Alert autonomyOverriddenAlert = new Alert( - "Autonomy level forced to manual due to disconnected coprocessor.", AlertType.kWarning); + "Autonomy level forced to manual due to disconnected coprocessor.", Alert.Level.MEDIUM); private final Alert visionDisconnectedAlert = - new Alert("Coprocessor disconnected", AlertType.kError); - private final Alert lowBatteryAlert = new Alert("Battery voltage low", AlertType.kWarning); + new Alert("Coprocessor disconnected", Alert.Level.HIGH); + private final Alert lowBatteryAlert = new Alert("Battery voltage low", Alert.Level.MEDIUM); // These constants will give a burst of two low battery voltage alerts, then one every second. private final TokenBucket lowBatteryAlertRateLimiter = new TokenBucket(200, 2); @@ -272,7 +270,7 @@ private void initializePositionBasedStrategyTriggers() { .onTrue( new InstantCommand( () -> { - if (DriverStation.isTeleopEnabled() + if (DriverStationBackend.isTeleopEnabled() && effectiveAutonomyLevel == AutonomyLevel.Smart) { shotMode = ShotMode.Hub; } @@ -280,7 +278,7 @@ private void initializePositionBasedStrategyTriggers() { .onFalse( new InstantCommand( () -> { - if (DriverStation.isTeleopEnabled() + if (DriverStationBackend.isTeleopEnabled() && effectiveAutonomyLevel == AutonomyLevel.Smart) { shotMode = ShotMode.Pass; } @@ -770,7 +768,7 @@ private void updateTurretDependencies(TurretSubsystem turret) { turret.setRobotHeading(drive.getRotation()); }); - boolean shouldStopForShootingDisabled = !shootingEnabled && !DriverStation.isTest(); + boolean shouldStopForShootingDisabled = !shootingEnabled && !DriverStationBackend.isUtility(); // Piggyback off of the intake stopping logic to save power during defense turret.setShouldStopMoving( @@ -813,7 +811,7 @@ private void updateIntakeDependencies(IntakeSubsystem intake) { * methods run. */ public void coordinateRobotActions() { - long startTimeUs = RobotController.getFPGATime(); + long startTimeUs = RobotController.getTime(); updateMatchState(); @@ -828,7 +826,7 @@ public void coordinateRobotActions() { if (isIntakeBoosted) { rollerSpeed = JsonConstants.intakeConstants.intakeTeleOpBoostedRollerSpeed; } - if (DriverStation.isAutonomous()) { + if (DriverStationBackend.isAutonomous()) { rollerSpeed = JsonConstants.intakeConstants.intakeAutoRollerSpeed; } intake.runRollers(rollerSpeed); @@ -865,7 +863,7 @@ public void coordinateRobotActions() { autonomyOverriddenAlert.set(effectiveAutonomyLevel != autonomyLevel); - if (DriverStation.isDisabled()) { + if (DriverStationBackend.isDisabled()) { boolean lowVoltage = JsonConstants.robotInfo.batteryVoltageAlert.isBatteryBelowThreshold( RobotController.getBatteryVoltage()); @@ -873,7 +871,7 @@ public void coordinateRobotActions() { lowBatteryAlertRateLimiter.increment(); if (lowVoltage && lowBatteryAlertRateLimiter.consumeTokens(TOKENS_PER_ALERT) - && !(DriverStation.isFMSAttached())) { + && !(DriverStationBackend.isFMSAttached())) { Elastic.sendNotification( new Elastic.Notification( Elastic.NotificationLevel.WARNING, @@ -900,7 +898,7 @@ public void coordinateRobotActions() { drive .map(drive -> AllianceBasedFieldConstants.isInAllianceZone(drive.getPose())) .orElse(true) - || !DriverStation.isAutonomous(); + || !DriverStationBackend.isAutonomous(); // canPassPastNet is true when either: // - We are not in passing mode (so net isn't a concern) @@ -968,7 +966,7 @@ public void coordinateRobotActions() { transferRoller -> transferRoller.setTargetVelocity(RadiansPerSecond.zero())); } - long shotCalculationStartTimeUs = RobotController.getFPGATime(); + long shotCalculationStartTimeUs = RobotController.getTime(); // Select a passing target based on where we are if (drive @@ -994,7 +992,7 @@ public void coordinateRobotActions() { case Manual -> drive.map(this::aimForManualShot).orElse(false); }; } - long shotCalculationEndTimeUs = RobotController.getFPGATime(); + long shotCalculationEndTimeUs = RobotController.getTime(); if (JsonConstants.featureFlags.logPeriodicTiming) { Logger.recordOutput( "PeriodicTime/CoordinateRobotActions/shotCalculationMs", @@ -1025,7 +1023,7 @@ public void coordinateRobotActions() { shooter.ifPresent(shooter -> shooter.stopShooter()); } - long endTimeUs = RobotController.getFPGATime(); + long endTimeUs = RobotController.getTime(); if (JsonConstants.featureFlags.logPeriodicTiming) { Logger.recordOutput( "PeriodicTime/CoordinateRobotActions/totalMs", (endTimeUs - startTimeUs) / 1000.0); @@ -1180,10 +1178,10 @@ private void aimForTestModeShot(Drive driveInstance) { private boolean shouldStowHoodBasedOnMovement(Drive drive, HoodSubsystem hood) { Pose2d robotPose = drive.getPose(); - ChassisSpeeds robotRelativeSpeeds = drive.getChassisSpeeds(); + ChassisVelocities robotRelativeSpeeds = drive.getChassisVelocities(); Translation2d fieldCentricSpeeds = new Translation2d( - robotRelativeSpeeds.vxMetersPerSecond, robotRelativeSpeeds.vyMetersPerSecond) + robotRelativeSpeeds.vx, robotRelativeSpeeds.vy) .rotateBy(robotPose.getRotation()); Translation2d shooterPose = @@ -1320,10 +1318,10 @@ private boolean runShotCalculatorWithDrive(Drive driveInstance) { ShotTarget target = getShotTargetFromPose(robotPose); - ChassisSpeeds robotRelativeSpeeds = driveInstance.getChassisSpeeds(); - ChassisSpeeds fieldCentricSpeeds = - ChassisSpeeds.fromRobotRelativeSpeeds( - driveInstance.getChassisSpeeds(), robotPose.getRotation()); + ChassisVelocities robotRelativeSpeeds = driveInstance.getChassisVelocities(); + ChassisVelocities fieldCentricSpeeds = + driveInstance.getChassisVelocities().toFieldRelative( + robotPose.getRotation()); /* Calculate the additional velocity caused by the rotation of the robot @@ -1344,7 +1342,7 @@ private boolean runShotCalculatorWithDrive(Drive driveInstance) { However, we can accomplish this math using Translation3d.cross instead: */ - double omega = robotRelativeSpeeds.omegaRadiansPerSecond; + double omega = robotRelativeSpeeds.omega; Translation3d omega_vec = new Translation3d(0, 0, omega); Translation3d robotToShooterTranslation = @@ -1362,8 +1360,8 @@ private boolean runShotCalculatorWithDrive(Drive driveInstance) { // in the air in the same way as the shooter curves on the ground. Translation2d shooterVelocity = new Translation2d( - fieldCentricSpeeds.vxMetersPerSecond + vRot.get(0), - fieldCentricSpeeds.vyMetersPerSecond + vRot.get(1)); + fieldCentricSpeeds.vx + vRot.get(0), + fieldCentricSpeeds.vy + vRot.get(1)); MapBasedShotInfo shot = ShotCalculations.calculateShotFromMap( @@ -1389,7 +1387,7 @@ private boolean runShotCalculatorWithDrive(Drive driveInstance) { /** Update the MatchState each periodic loop */ private void updateMatchState() { - if (DriverStation.isEnabled()) { + if (DriverStationBackend.isEnabled()) { matchState.enabledPeriodic(isWonAutoPressed.getAsBoolean(), isLostAutoPressed.getAsBoolean()); } else { matchState.disabledPeriodic(); @@ -1433,7 +1431,7 @@ private ShotInfo getCurrentShot(ShotInfo idealShot) { return new ShotInfo( hood.map(hood -> hood.getCurrentExitPitch().in(Radians)) .orElse( - MathUtil.clamp( + Math.clamp( idealShot.pitchRadians(), Math.toRadians(90 - JsonConstants.hoodConstants.maxHoodAngle.in(Degrees)), Math.toRadians(90 - JsonConstants.hoodConstants.minHoodAngle.in(Degrees)))), diff --git a/src/main/java/frc/robot/DependencyOrderedExecutor.java b/src/main/java/frc/robot/DependencyOrderedExecutor.java index 68f5e628..bcbcb55a 100644 --- a/src/main/java/frc/robot/DependencyOrderedExecutor.java +++ b/src/main/java/frc/robot/DependencyOrderedExecutor.java @@ -1,10 +1,10 @@ package frc.robot; -import static edu.wpi.first.units.Units.Seconds; +import static org.wpilib.units.Units.Seconds; -import edu.wpi.first.units.measure.Time; -import edu.wpi.first.wpilibj.TimedRobot; -import edu.wpi.first.wpilibj.Watchdog; +import org.wpilib.units.measure.Time; +import org.wpilib.framework.TimedRobot; +import org.wpilib.system.Watchdog; import java.io.PrintWriter; import java.util.HashMap; import java.util.List; @@ -53,7 +53,7 @@ private record NamedAction(String name, Runnable action) {} * period. */ public DependencyOrderedExecutor() { - watchdog = new Watchdog(Seconds.of(TimedRobot.kDefaultPeriod), () -> {}); + watchdog = new Watchdog(Seconds.of(TimedRobot.DEFAULT_PERIOD), () -> {}); } /** diff --git a/src/main/java/frc/robot/InitSubsystems.java b/src/main/java/frc/robot/InitSubsystems.java index a75726ef..becd9e00 100644 --- a/src/main/java/frc/robot/InitSubsystems.java +++ b/src/main/java/frc/robot/InitSubsystems.java @@ -13,8 +13,8 @@ import coppercore.wpilib_interface.subsystems.motors.talonfx.MotorIOTalonFX; import coppercore.wpilib_interface.subsystems.motors.talonfx.MotorIOTalonFXSim; import coppercore.wpilib_interface.subsystems.sim.CoppercoreSimAdapter; -import edu.wpi.first.apriltag.AprilTagFieldLayout; -import edu.wpi.first.math.geometry.Transform3d; +import org.wpilib.vision.apriltag.AprilTagFieldLayout; +import org.wpilib.math.geometry.Transform3d; import frc.robot.constants.JsonConstants; import frc.robot.subsystems.climber.ClimberSubsystem; import frc.robot.subsystems.drive.Drive; diff --git a/src/main/java/frc/robot/Main.java b/src/main/java/frc/robot/Main.java index 15d87e93..b5169129 100644 --- a/src/main/java/frc/robot/Main.java +++ b/src/main/java/frc/robot/Main.java @@ -7,7 +7,8 @@ package frc.robot; -import edu.wpi.first.wpilibj.RobotBase; +import org.wpilib.framework.RobotBase; +import org.wpilib.framework.TimedRobot; /** * Do NOT add any static variables to this class, or any initialization at all. Unless you know what @@ -23,6 +24,6 @@ private Main() {} *

If you change your main robot class, change the parameter type. */ public static void main(String... args) { - RobotBase.startRobot(Robot::new); + RobotBase.startRobot(TimedRobot.class); } } diff --git a/src/main/java/frc/robot/Robot.java b/src/main/java/frc/robot/Robot.java index 878ee0b9..f6c4b99d 100644 --- a/src/main/java/frc/robot/Robot.java +++ b/src/main/java/frc/robot/Robot.java @@ -11,15 +11,16 @@ import com.ctre.phoenix6.unmanaged.Unmanaged; import coppercore.monitors.TotalCurrentCalculator; import coppercore.wpilib_interface.subsystems.StatusSignalRefresher; -import edu.wpi.first.hal.AllianceStationID; -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.RobotController; -import edu.wpi.first.wpilibj.simulation.DriverStationSim; -import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; -import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.CommandScheduler; +import org.wpilib.hardware.hal.AllianceStationID; +import org.wpilib.hardware.hal.RobotMode; +import org.wpilib.math.geometry.Pose2d; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.driverstation.internal.DriverStationBackend; +import org.wpilib.system.RobotController; +import org.wpilib.simulation.DriverStationSim; +import org.wpilib.smartdashboard.SmartDashboard; +import org.wpilib.command2.Command; +import org.wpilib.command2.CommandScheduler; import frc.robot.constants.FeatureFlags; import frc.robot.constants.JsonConstants; import org.littletonrobotics.junction.LogFileUtil; @@ -88,7 +89,7 @@ public Robot() { // This got our mean cycle time (admittedly while not seeing any tags) down to 15ms } - DriverStation.silenceJoystickConnectionWarning(true); + DriverStationBackend.silenceJoystickConnectionWarning(true); // Start AdvantageKit logger Logger.start(); @@ -110,9 +111,9 @@ public void robotPeriodic() { // Threads.setCurrentThreadPriority(true, 99); // Refresh all status signals, must be done before any IOs run updateInputs - long refresherStartTimeUs = RobotController.getFPGATime(); + long refresherStartTimeUs = RobotController.getTime(); StatusSignalRefresher.refreshAll(); - long refresherEndTimeUs = RobotController.getFPGATime(); + long refresherEndTimeUs = RobotController.getTime(); if (JsonConstants.featureFlags.logPeriodicTiming) { Logger.recordOutput( "PeriodicTime/statusSignalRefresherMs", @@ -189,14 +190,14 @@ public void teleopPeriodic() {} /** This function is called once when test mode is enabled. */ @Override - public void testInit() { + public void utilityInit() { // Cancels all running commands at the start of test mode. CommandScheduler.getInstance().cancelAll(); } /** This function is called periodically during test mode. */ @Override - public void testPeriodic() {} + public void utilityPeriodic() {} /** This function is called once when the robot is first started up. */ @Override @@ -227,13 +228,13 @@ public AutoTestingSimulation(Robot robot) { // Initialize the auto testing simulation, set up network table listeners, etc. allianceStationChooser = new LoggedDashboardChooser<>(AUTO_TESTING_PREFIX + "AllianceStation"); - allianceStationChooser.addDefaultOption("Unknown", AllianceStationID.Unknown); - allianceStationChooser.addOption("Red 1", AllianceStationID.Red1); - allianceStationChooser.addOption("Red 2", AllianceStationID.Red2); - allianceStationChooser.addOption("Red 3", AllianceStationID.Red3); - allianceStationChooser.addOption("Blue 1", AllianceStationID.Blue1); - allianceStationChooser.addOption("Blue 2", AllianceStationID.Blue2); - allianceStationChooser.addOption("Blue 3", AllianceStationID.Blue3); + allianceStationChooser.addDefaultOption("Unknown", AllianceStationID.UNKNOWN); + allianceStationChooser.addOption("Red 1", AllianceStationID.RED_1); + allianceStationChooser.addOption("Red 2", AllianceStationID.RED_2); + allianceStationChooser.addOption("Red 3", AllianceStationID.RED_3); + allianceStationChooser.addOption("Blue 1", AllianceStationID.BLUE_1); + allianceStationChooser.addOption("Blue 2", AllianceStationID.BLUE_2); + allianceStationChooser.addOption("Blue 3", AllianceStationID.BLUE_3); SmartDashboard.putBoolean(AUTO_TESTING_PREFIX + "RobotEnabled", false); SmartDashboard.putBoolean(AUTO_TESTING_PREFIX + "AutoEnabled", false); @@ -255,13 +256,13 @@ public void update() { DriverStationSim.notifyNewData(); if (SmartDashboard.getBoolean(AUTO_TESTING_PREFIX + "StartAuto", false)) { - DriverStationSim.setAutonomous(true); + DriverStationSim.setRobotMode(RobotMode.AUTONOMOUS); DriverStationSim.setEnabled(true); SmartDashboard.putBoolean(AUTO_TESTING_PREFIX + "StartAuto", false); } if (SmartDashboard.getBoolean(AUTO_TESTING_PREFIX + "StopAuto", false)) { - DriverStationSim.setAutonomous(false); + DriverStationSim.setRobotMode(RobotMode.TELEOPERATED); DriverStationSim.setEnabled(false); SmartDashboard.putBoolean(AUTO_TESTING_PREFIX + "StopAuto", false); } @@ -279,8 +280,8 @@ public void update() { DriverStationSim.notifyNewData(); - SmartDashboard.putBoolean(AUTO_TESTING_PREFIX + "RobotEnabled", DriverStation.isEnabled()); - SmartDashboard.putBoolean(AUTO_TESTING_PREFIX + "AutoEnabled", DriverStation.isAutonomous()); + SmartDashboard.putBoolean(AUTO_TESTING_PREFIX + "RobotEnabled", DriverStationBackend.isEnabled()); + SmartDashboard.putBoolean(AUTO_TESTING_PREFIX + "AutoEnabled", DriverStationBackend.isAutonomous()); } } } diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index 35af51d8..224e0272 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -7,27 +7,26 @@ package frc.robot; -import static edu.wpi.first.units.Units.Meters; -import static edu.wpi.first.units.Units.Radians; +import static org.wpilib.units.Units.Meters; +import static org.wpilib.units.Units.Radians; import coppercore.metadata.CopperCoreMetadata; import coppercore.monitors.TotalCurrentCalculator; import coppercore.parameter_tools.json.JSONHandler; -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.Rotation3d; -import edu.wpi.first.math.geometry.Transform3d; -import edu.wpi.first.math.geometry.Translation3d; -import edu.wpi.first.units.measure.Angle; -import edu.wpi.first.units.measure.Distance; -import edu.wpi.first.units.measure.Time; -import edu.wpi.first.wpilibj.GenericHID; -import edu.wpi.first.wpilibj.RobotController; -import edu.wpi.first.wpilibj.XboxController; -import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.CommandScheduler; -import edu.wpi.first.wpilibj2.command.sysid.SysIdRoutine; +import org.wpilib.math.geometry.Pose2d; +import org.wpilib.math.geometry.Pose3d; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.math.geometry.Rotation3d; +import org.wpilib.math.geometry.Transform3d; +import org.wpilib.math.geometry.Translation3d; +import org.wpilib.units.measure.Angle; +import org.wpilib.units.measure.Distance; +import org.wpilib.units.measure.Time; +import org.wpilib.driverstation.GenericHID; +import org.wpilib.system.RobotController; +import org.wpilib.command2.Command; +import org.wpilib.command2.CommandScheduler; +import org.wpilib.command2.sysid.SysIdRoutine; import frc.robot.Constants.Mode; import frc.robot.DependencyOrderedExecutor.ActionKey; import frc.robot.commands.DriveCommands; @@ -273,11 +272,11 @@ public void updateRobotModel() { */ void processHTTPRequests() { if (JsonConstants.featureFlags.useTuningServer) { - long startTimeUs = RobotController.getFPGATime(); + long startTimeUs = RobotController.getTime(); jsonHandler.drainQueuedHttpActions(); - long endTimeUs = RobotController.getFPGATime(); + long endTimeUs = RobotController.getTime(); if (JsonConstants.featureFlags.logPeriodicTiming) { Logger.recordOutput("PeriodicTime/httpRequestsMs", (endTimeUs - startTimeUs) / 1000.0); } @@ -328,8 +327,8 @@ private void createAutoChooser(Drive drive) { /** * Use this method to define your button->command mappings. Buttons can be created by * instantiating a {@link GenericHID} or one of its subclasses ({@link - * edu.wpi.first.wpilibj.Joystick} or {@link XboxController}), and then passing it to a {@link - * edu.wpi.first.wpilibj2.command.button.JoystickButton}. + * org.wpilib.driverstation.Joystick} or {@link XboxController}), and then passing it to a {@link + * org.wpilib.command2.button.JoystickButton}. */ private void configureButtonBindings() { coordinationLayer.initBindings(); diff --git a/src/main/java/frc/robot/ShotCalculations.java b/src/main/java/frc/robot/ShotCalculations.java index f6cbdd0a..9ca13330 100644 --- a/src/main/java/frc/robot/ShotCalculations.java +++ b/src/main/java/frc/robot/ShotCalculations.java @@ -1,16 +1,15 @@ package frc.robot; -import static edu.wpi.first.units.Units.MetersPerSecond; -import static edu.wpi.first.units.Units.Seconds; - -import edu.wpi.first.math.MathUtil; -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.math.geometry.Translation3d; -import edu.wpi.first.math.geometry.Twist2d; -import edu.wpi.first.math.kinematics.ChassisSpeeds; -import edu.wpi.first.units.measure.LinearVelocity; +import static org.wpilib.units.Units.MetersPerSecond; +import static org.wpilib.units.Units.Seconds; + +import org.wpilib.math.geometry.Pose2d; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.math.geometry.Translation2d; +import org.wpilib.math.geometry.Translation3d; +import org.wpilib.math.geometry.Twist2d; +import org.wpilib.math.kinematics.ChassisVelocities; +import org.wpilib.units.measure.LinearVelocity; import frc.robot.constants.AllianceBasedFieldConstants; import frc.robot.constants.FieldLocations; import frc.robot.constants.JsonConstants; @@ -34,14 +33,14 @@ public static record ShotInfo(double pitchRadians, double yawRadians, double tim public Translation3d[] projectMotion( double shooterVelocityMps, Translation3d initialPosition, - ChassisSpeeds fieldRelativeRobotVel, + ChassisVelocities fieldRelativeRobotVel, double pointsPerMeter) { List trajectory = new ArrayList<>(); double vxy = shooterVelocityMps * Math.cos(pitchRadians()); - double vx = vxy * Math.cos(yawRadians()) + fieldRelativeRobotVel.vxMetersPerSecond; - double vy = vxy * Math.sin(yawRadians()) + fieldRelativeRobotVel.vyMetersPerSecond; + double vx = vxy * Math.cos(yawRadians()) + fieldRelativeRobotVel.vx; + double vy = vxy * Math.sin(yawRadians()) + fieldRelativeRobotVel.vy; double vz = shooterVelocityMps * Math.sin(pitchRadians()); Translation3d position = initialPosition; @@ -130,7 +129,7 @@ public static Optional calculateStationaryShot( public static Optional calculateMovingShot( Translation3d shooterPosition, Translation3d goalPosition, - ChassisSpeeds robotVelocity, + ChassisVelocities robotVelocity, LinearVelocity shooterVelocity, ShotType shotType, Optional lastShot) { @@ -157,7 +156,7 @@ public static Optional calculateMovingShot( t = solution.timeSeconds; var vRobot = - new Translation3d(robotVelocity.vxMetersPerSecond, robotVelocity.vyMetersPerSecond, 0); + new Translation3d(robotVelocity.vx, robotVelocity.vy, 0); Translation3d effectiveGoal = goalPosition.minus(vRobot.times(t)); @@ -247,7 +246,7 @@ public record MapBasedShotInfo( */ public static MapBasedShotInfo calculateShotFromMap( Pose2d robotPose, - ChassisSpeeds robotRelativeChassisSpeeds, + ChassisVelocities robotRelativeChassisSpeeds, Translation2d fieldRelativeShooterVelocity, ShotTarget target) { Translation2d targetPosition = target.getTranslation(); @@ -255,11 +254,11 @@ public static MapBasedShotInfo calculateShotFromMap( double lookaheadTimeSeconds = JsonConstants.shotMaps.mechanismCompensationDelay.in(Seconds); Pose2d lookaheadPose = - robotPose.exp( + robotPose.plus( new Twist2d( - robotRelativeChassisSpeeds.vxMetersPerSecond * lookaheadTimeSeconds, - robotRelativeChassisSpeeds.vyMetersPerSecond * lookaheadTimeSeconds, - robotRelativeChassisSpeeds.omegaRadiansPerSecond * lookaheadTimeSeconds)); + robotRelativeChassisSpeeds.vx * lookaheadTimeSeconds, + robotRelativeChassisSpeeds.vy * lookaheadTimeSeconds, + robotRelativeChassisSpeeds.omega * lookaheadTimeSeconds).exp()); Logger.recordOutput("ShotCalculations/MapBased/lookaheadPose", lookaheadPose); @@ -290,7 +289,7 @@ public static MapBasedShotInfo calculateShotFromMap( if (distanceXYMeters < minDistanceMeters || distanceXYMeters > maxDistanceMeters) { // When clamping, the shot is no longer real. isShotReal = false; - distanceXYMeters = MathUtil.clamp(distanceXYMeters, minDistanceMeters, maxDistanceMeters); + distanceXYMeters = Math.clamp(distanceXYMeters, minDistanceMeters, maxDistanceMeters); } Logger.recordOutput("ShotCalculations/MapBased/ClampedShotDistanceMeters", distanceXYMeters); @@ -400,7 +399,7 @@ public static MapBasedShotInfo calculateShotFromMap( // When clamping, the shot is no longer real. isShotReal = false; virtualDistanceXYMeters = - MathUtil.clamp(virtualDistanceXYMeters, minDistanceMeters, maxDistanceMeters); + Math.clamp(virtualDistanceXYMeters, minDistanceMeters, maxDistanceMeters); } Logger.recordOutput( "ShotCalculations/MapBased/ClampedVirtualDistanceMeters", virtualDistanceXYMeters); diff --git a/src/main/java/frc/robot/auto/Auto.java b/src/main/java/frc/robot/auto/Auto.java index 6b5a6ff2..52bea6f6 100644 --- a/src/main/java/frc/robot/auto/Auto.java +++ b/src/main/java/frc/robot/auto/Auto.java @@ -1,6 +1,6 @@ package frc.robot.auto; -import edu.wpi.first.wpilibj2.command.Command; +import org.wpilib.command2.Command; import frc.robot.auto.AutoAction.AutoActionContext; public class Auto { diff --git a/src/main/java/frc/robot/auto/AutoAction.java b/src/main/java/frc/robot/auto/AutoAction.java index bbbc4662..a7eaf7ef 100644 --- a/src/main/java/frc/robot/auto/AutoAction.java +++ b/src/main/java/frc/robot/auto/AutoAction.java @@ -2,7 +2,7 @@ import coppercore.parameter_tools.json.annotations.JsonSubtype; import coppercore.parameter_tools.json.annotations.JsonType; -import edu.wpi.first.wpilibj2.command.Command; +import org.wpilib.command2.Command; import frc.robot.CoordinationLayer; import frc.robot.auto.coordinationLayer.ClimbHangAction; import frc.robot.auto.coordinationLayer.ClimbSearchAction; diff --git a/src/main/java/frc/robot/auto/Autos.java b/src/main/java/frc/robot/auto/Autos.java index cc3bb25d..51e661ff 100644 --- a/src/main/java/frc/robot/auto/Autos.java +++ b/src/main/java/frc/robot/auto/Autos.java @@ -4,10 +4,10 @@ import com.pathplanner.lib.util.FileVersionException; import com.pathplanner.lib.util.FlippingUtil; import coppercore.parameter_tools.json.annotations.JSONExclude; -import edu.wpi.first.math.geometry.Pose2d; -import edu.wpi.first.math.geometry.Rotation2d; -import edu.wpi.first.wpilibj.Filesystem; -import edu.wpi.first.wpilibj2.command.Command; +import org.wpilib.math.geometry.Pose2d; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.system.Filesystem; +import org.wpilib.command2.Command; import frc.robot.CoordinationLayer; import frc.robot.constants.FieldConstants; import frc.robot.subsystems.drive.DriveCoordinator; diff --git a/src/main/java/frc/robot/auto/coordinationLayer/ClimbHangAction.java b/src/main/java/frc/robot/auto/coordinationLayer/ClimbHangAction.java index 8c6df7bd..6a955c34 100644 --- a/src/main/java/frc/robot/auto/coordinationLayer/ClimbHangAction.java +++ b/src/main/java/frc/robot/auto/coordinationLayer/ClimbHangAction.java @@ -1,7 +1,7 @@ package frc.robot.auto.coordinationLayer; -import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.InstantCommand; +import org.wpilib.command2.Command; +import org.wpilib.command2.InstantCommand; import frc.robot.auto.AutoAction; public class ClimbHangAction extends AutoAction { diff --git a/src/main/java/frc/robot/auto/coordinationLayer/ClimbSearchAction.java b/src/main/java/frc/robot/auto/coordinationLayer/ClimbSearchAction.java index 01e95860..4b078135 100644 --- a/src/main/java/frc/robot/auto/coordinationLayer/ClimbSearchAction.java +++ b/src/main/java/frc/robot/auto/coordinationLayer/ClimbSearchAction.java @@ -1,6 +1,6 @@ package frc.robot.auto.coordinationLayer; -import edu.wpi.first.wpilibj2.command.Command; +import org.wpilib.command2.Command; import frc.robot.auto.AutoAction; public class ClimbSearchAction extends AutoAction { diff --git a/src/main/java/frc/robot/auto/coordinationLayer/DeployIntakeAction.java b/src/main/java/frc/robot/auto/coordinationLayer/DeployIntakeAction.java index 8df640ed..868ec98b 100644 --- a/src/main/java/frc/robot/auto/coordinationLayer/DeployIntakeAction.java +++ b/src/main/java/frc/robot/auto/coordinationLayer/DeployIntakeAction.java @@ -1,7 +1,7 @@ package frc.robot.auto.coordinationLayer; -import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.InstantCommand; +import org.wpilib.command2.Command; +import org.wpilib.command2.InstantCommand; import frc.robot.auto.AutoAction; public class DeployIntakeAction extends AutoAction { diff --git a/src/main/java/frc/robot/auto/coordinationLayer/StartShooting.java b/src/main/java/frc/robot/auto/coordinationLayer/StartShooting.java index d445e529..9e747b2b 100644 --- a/src/main/java/frc/robot/auto/coordinationLayer/StartShooting.java +++ b/src/main/java/frc/robot/auto/coordinationLayer/StartShooting.java @@ -1,7 +1,7 @@ package frc.robot.auto.coordinationLayer; -import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.InstantCommand; +import org.wpilib.command2.Command; +import org.wpilib.command2.InstantCommand; import frc.robot.auto.AutoAction; public class StartShooting extends AutoAction { diff --git a/src/main/java/frc/robot/auto/coordinationLayer/StopShooting.java b/src/main/java/frc/robot/auto/coordinationLayer/StopShooting.java index b87a3a91..1de727d7 100644 --- a/src/main/java/frc/robot/auto/coordinationLayer/StopShooting.java +++ b/src/main/java/frc/robot/auto/coordinationLayer/StopShooting.java @@ -1,7 +1,7 @@ package frc.robot.auto.coordinationLayer; -import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.InstantCommand; +import org.wpilib.command2.Command; +import org.wpilib.command2.InstantCommand; import frc.robot.auto.AutoAction; public class StopShooting extends AutoAction { diff --git a/src/main/java/frc/robot/auto/coordinationLayer/StowIntakeAction.java b/src/main/java/frc/robot/auto/coordinationLayer/StowIntakeAction.java index 8575968d..b7daec7a 100644 --- a/src/main/java/frc/robot/auto/coordinationLayer/StowIntakeAction.java +++ b/src/main/java/frc/robot/auto/coordinationLayer/StowIntakeAction.java @@ -1,7 +1,7 @@ package frc.robot.auto.coordinationLayer; -import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.InstantCommand; +import org.wpilib.command2.Command; +import org.wpilib.command2.InstantCommand; import frc.robot.auto.AutoAction; public class StowIntakeAction extends AutoAction { diff --git a/src/main/java/frc/robot/auto/drive/AutoPilotAction.java b/src/main/java/frc/robot/auto/drive/AutoPilotAction.java index d0a95526..c4365341 100644 --- a/src/main/java/frc/robot/auto/drive/AutoPilotAction.java +++ b/src/main/java/frc/robot/auto/drive/AutoPilotAction.java @@ -5,8 +5,8 @@ import com.therekrab.autopilot.APTarget; import com.therekrab.autopilot.Autopilot; import coppercore.wpilib_interface.tuning.PIDGains; -import edu.wpi.first.math.controller.PIDController; -import edu.wpi.first.wpilibj2.command.Command; +import org.wpilib.math.controller.PIDController; +import org.wpilib.command2.Command; import frc.robot.auto.Autos; import frc.robot.constants.JsonConstants; import frc.robot.subsystems.drive.DriveCoordinatorCommands; diff --git a/src/main/java/frc/robot/auto/drive/FollowPathPlannerPath.java b/src/main/java/frc/robot/auto/drive/FollowPathPlannerPath.java index 87a5bed5..aaa3e50d 100644 --- a/src/main/java/frc/robot/auto/drive/FollowPathPlannerPath.java +++ b/src/main/java/frc/robot/auto/drive/FollowPathPlannerPath.java @@ -5,7 +5,7 @@ import com.pathplanner.lib.config.RobotConfig; import com.pathplanner.lib.controllers.PPHolonomicDriveController; import com.pathplanner.lib.controllers.PathFollowingController; -import edu.wpi.first.wpilibj2.command.Command; +import org.wpilib.command2.Command; import frc.robot.subsystems.drive.DriveCoordinatorCommands; import java.io.IOException; import java.util.function.BooleanSupplier; @@ -49,8 +49,8 @@ public Command toCommand(AutoActionContext context) { new FollowPathCommand( path, drive::getPose, - drive::getChassisSpeeds, - (speeds, feedforwards) -> drive.setGoalSpeeds(speeds, false), + drive::getChassisVelocities, + (speeds, feedforwards) -> drive.setGoalVelocities(speeds, false), controller, config, FALSE)); diff --git a/src/main/java/frc/robot/auto/drive/StopDriveAction.java b/src/main/java/frc/robot/auto/drive/StopDriveAction.java index 6bdbabd9..9fa27e0a 100644 --- a/src/main/java/frc/robot/auto/drive/StopDriveAction.java +++ b/src/main/java/frc/robot/auto/drive/StopDriveAction.java @@ -1,6 +1,6 @@ package frc.robot.auto.drive; -import edu.wpi.first.wpilibj2.command.Command; +import org.wpilib.command2.Command; import frc.robot.subsystems.drive.DriveCoordinatorCommands; public class StopDriveAction extends DriveAutoAction { diff --git a/src/main/java/frc/robot/auto/drive/XBasedAutoPilotAction.java b/src/main/java/frc/robot/auto/drive/XBasedAutoPilotAction.java index c5d726ce..53183ec4 100644 --- a/src/main/java/frc/robot/auto/drive/XBasedAutoPilotAction.java +++ b/src/main/java/frc/robot/auto/drive/XBasedAutoPilotAction.java @@ -5,7 +5,7 @@ import com.therekrab.autopilot.APTarget; import com.therekrab.autopilot.Autopilot; import coppercore.wpilib_interface.tuning.PIDGains; -import edu.wpi.first.wpilibj2.command.Command; +import org.wpilib.command2.Command; import frc.robot.subsystems.drive.DriveCoordinatorCommands; public class XBasedAutoPilotAction extends AutoPilotAction { diff --git a/src/main/java/frc/robot/auto/general/AutoReference.java b/src/main/java/frc/robot/auto/general/AutoReference.java index efad573b..8c0e4b2b 100644 --- a/src/main/java/frc/robot/auto/general/AutoReference.java +++ b/src/main/java/frc/robot/auto/general/AutoReference.java @@ -1,6 +1,6 @@ package frc.robot.auto.general; -import edu.wpi.first.wpilibj2.command.Command; +import org.wpilib.command2.Command; import frc.robot.auto.AutoAction; public class AutoReference extends AutoAction { diff --git a/src/main/java/frc/robot/auto/general/Deadline.java b/src/main/java/frc/robot/auto/general/Deadline.java index 09da4111..1a45eaa9 100644 --- a/src/main/java/frc/robot/auto/general/Deadline.java +++ b/src/main/java/frc/robot/auto/general/Deadline.java @@ -1,6 +1,6 @@ package frc.robot.auto.general; -import edu.wpi.first.wpilibj2.command.Command; +import org.wpilib.command2.Command; import frc.robot.auto.AutoAction; import java.util.Objects; import java.util.stream.Stream; diff --git a/src/main/java/frc/robot/auto/general/NetworkConfigurableWait.java b/src/main/java/frc/robot/auto/general/NetworkConfigurableWait.java index 24654a61..53b42d72 100644 --- a/src/main/java/frc/robot/auto/general/NetworkConfigurableWait.java +++ b/src/main/java/frc/robot/auto/general/NetworkConfigurableWait.java @@ -1,13 +1,13 @@ package frc.robot.auto.general; -import static edu.wpi.first.units.Units.Seconds; +import static org.wpilib.units.Units.Seconds; import coppercore.parameter_tools.json.annotations.AfterJsonLoad; import coppercore.parameter_tools.json.annotations.JSONExclude; -import edu.wpi.first.units.measure.Time; -import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.DeferredCommand; -import edu.wpi.first.wpilibj2.command.WaitCommand; +import org.wpilib.units.measure.Time; +import org.wpilib.command2.Command; +import org.wpilib.command2.DeferredCommand; +import org.wpilib.command2.WaitCommand; import frc.robot.auto.AutoAction; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/frc/robot/auto/general/Parallel.java b/src/main/java/frc/robot/auto/general/Parallel.java index 17b672bb..771ad05c 100644 --- a/src/main/java/frc/robot/auto/general/Parallel.java +++ b/src/main/java/frc/robot/auto/general/Parallel.java @@ -1,7 +1,7 @@ package frc.robot.auto.general; -import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.ParallelCommandGroup; +import org.wpilib.command2.Command; +import org.wpilib.command2.ParallelCommandGroup; import frc.robot.auto.AutoAction; import java.util.List; import java.util.Objects; diff --git a/src/main/java/frc/robot/auto/general/Print.java b/src/main/java/frc/robot/auto/general/Print.java index 27817f1c..c088ffdd 100644 --- a/src/main/java/frc/robot/auto/general/Print.java +++ b/src/main/java/frc/robot/auto/general/Print.java @@ -1,7 +1,7 @@ package frc.robot.auto.general; -import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.InstantCommand; +import org.wpilib.command2.Command; +import org.wpilib.command2.InstantCommand; import frc.robot.auto.AutoAction; // This will allow us to print messages to the console during auto to help with debugging diff --git a/src/main/java/frc/robot/auto/general/Race.java b/src/main/java/frc/robot/auto/general/Race.java index 77e0331d..9b297dc7 100644 --- a/src/main/java/frc/robot/auto/general/Race.java +++ b/src/main/java/frc/robot/auto/general/Race.java @@ -1,7 +1,7 @@ package frc.robot.auto.general; -import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.ParallelRaceGroup; +import org.wpilib.command2.Command; +import org.wpilib.command2.ParallelRaceGroup; import frc.robot.auto.AutoAction; import java.util.List; import java.util.Objects; diff --git a/src/main/java/frc/robot/auto/general/Sequence.java b/src/main/java/frc/robot/auto/general/Sequence.java index baa9e762..3959afad 100644 --- a/src/main/java/frc/robot/auto/general/Sequence.java +++ b/src/main/java/frc/robot/auto/general/Sequence.java @@ -1,7 +1,7 @@ package frc.robot.auto.general; -import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.SequentialCommandGroup; +import org.wpilib.command2.Command; +import org.wpilib.command2.SequentialCommandGroup; import frc.robot.auto.AutoAction; import java.util.List; import java.util.Objects; diff --git a/src/main/java/frc/robot/auto/general/Wait.java b/src/main/java/frc/robot/auto/general/Wait.java index 6153d86b..ec789b0d 100644 --- a/src/main/java/frc/robot/auto/general/Wait.java +++ b/src/main/java/frc/robot/auto/general/Wait.java @@ -1,8 +1,8 @@ package frc.robot.auto.general; -import edu.wpi.first.units.measure.Time; -import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.WaitCommand; +import org.wpilib.units.measure.Time; +import org.wpilib.command2.Command; +import org.wpilib.command2.WaitCommand; import frc.robot.auto.AutoAction; public class Wait extends AutoAction { diff --git a/src/main/java/frc/robot/autogen/Dsl.java b/src/main/java/frc/robot/autogen/Dsl.java index 28a05a00..28d5f3d7 100644 --- a/src/main/java/frc/robot/autogen/Dsl.java +++ b/src/main/java/frc/robot/autogen/Dsl.java @@ -1,20 +1,20 @@ package frc.robot.autogen; -import static edu.wpi.first.units.Units.Degrees; -import static edu.wpi.first.units.Units.Meters; -import static edu.wpi.first.units.Units.Seconds; +import static org.wpilib.units.Units.Degrees; +import static org.wpilib.units.Units.Meters; +import static org.wpilib.units.Units.Seconds; import com.therekrab.autopilot.APConstraints; import com.therekrab.autopilot.APProfile; import com.therekrab.autopilot.APTarget; import coppercore.wpilib_interface.tuning.PIDGains; -import edu.wpi.first.math.geometry.Pose2d; -import edu.wpi.first.math.geometry.Rotation2d; -import edu.wpi.first.math.geometry.Transform2d; -import edu.wpi.first.math.geometry.Translation2d; -import edu.wpi.first.units.measure.Angle; -import edu.wpi.first.units.measure.Distance; -import edu.wpi.first.units.measure.Time; +import org.wpilib.math.geometry.Pose2d; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.math.geometry.Transform2d; +import org.wpilib.math.geometry.Translation2d; +import org.wpilib.units.measure.Angle; +import org.wpilib.units.measure.Distance; +import org.wpilib.units.measure.Time; import frc.robot.auto.AutoAction; import frc.robot.auto.coordinationLayer.ClimbHangAction; import frc.robot.auto.coordinationLayer.ClimbSearchAction; diff --git a/src/main/java/frc/robot/autogen/Field.java b/src/main/java/frc/robot/autogen/Field.java index 0bb07462..bd1e96c9 100644 --- a/src/main/java/frc/robot/autogen/Field.java +++ b/src/main/java/frc/robot/autogen/Field.java @@ -1,10 +1,10 @@ package frc.robot.autogen; -import edu.wpi.first.hal.HAL; -import edu.wpi.first.math.geometry.Pose2d; -import edu.wpi.first.math.geometry.Rotation2d; -import edu.wpi.first.math.geometry.Transform2d; -import edu.wpi.first.math.geometry.Translation2d; +import org.wpilib.hardware.hal.HAL; +import org.wpilib.math.geometry.Pose2d; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.math.geometry.Transform2d; +import org.wpilib.math.geometry.Translation2d; import frc.robot.constants.FieldConstants; import frc.robot.constants.JsonConstants; diff --git a/src/main/java/frc/robot/autogen/GenerateAutos.java b/src/main/java/frc/robot/autogen/GenerateAutos.java index 5c9ae57d..ade6401f 100644 --- a/src/main/java/frc/robot/autogen/GenerateAutos.java +++ b/src/main/java/frc/robot/autogen/GenerateAutos.java @@ -27,8 +27,8 @@ import coppercore.parameter_tools.json.JSONSyncConfig; import coppercore.parameter_tools.json.JSONSyncConfigBuilder; import coppercore.parameter_tools.json.helpers.JSONConverter; -import edu.wpi.first.math.geometry.Pose2d; -import edu.wpi.first.math.geometry.Rotation2d; +import org.wpilib.math.geometry.Pose2d; +import org.wpilib.math.geometry.Rotation2d; import frc.robot.auto.Auto; import frc.robot.auto.AutoAction; import frc.robot.auto.Autos; diff --git a/src/main/java/frc/robot/commands/DriveCommands.java b/src/main/java/frc/robot/commands/DriveCommands.java index 80b02f14..816c4a65 100644 --- a/src/main/java/frc/robot/commands/DriveCommands.java +++ b/src/main/java/frc/robot/commands/DriveCommands.java @@ -7,21 +7,21 @@ package frc.robot.commands; -import edu.wpi.first.math.MathUtil; -import edu.wpi.first.math.controller.ProfiledPIDController; -import edu.wpi.first.math.filter.SlewRateLimiter; -import edu.wpi.first.math.geometry.Pose2d; -import edu.wpi.first.math.geometry.Rotation2d; -import edu.wpi.first.math.geometry.Transform2d; -import edu.wpi.first.math.geometry.Translation2d; -import edu.wpi.first.math.kinematics.ChassisSpeeds; -import edu.wpi.first.math.trajectory.TrapezoidProfile; -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; +import org.wpilib.math.util.MathUtil; +import org.wpilib.math.controller.ProfiledPIDController; +import org.wpilib.math.filter.SlewRateLimiter; +import org.wpilib.math.geometry.Pose2d; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.math.geometry.Transform2d; +import org.wpilib.math.geometry.Translation2d; +import org.wpilib.math.kinematics.ChassisVelocities; +import org.wpilib.math.trajectory.TrapezoidProfile; +import org.wpilib.math.util.Units; +import org.wpilib.driverstation.internal.DriverStationBackend; +import org.wpilib.driverstation.Alliance; +import org.wpilib.system.Timer; +import org.wpilib.command2.Command; +import org.wpilib.command2.Commands; import frc.robot.constants.JsonConstants; import frc.robot.subsystems.drive.Drive; import java.text.DecimalFormat; @@ -79,17 +79,16 @@ public static Command joystickDrive( omega = Math.copySign(omega * omega, omega); // Convert to field relative speeds & send command - ChassisSpeeds speeds = - new ChassisSpeeds( + ChassisVelocities speeds = + new ChassisVelocities( linearVelocity.getX() * drive.getMaxLinearSpeedMetersPerSec(), linearVelocity.getY() * drive.getMaxLinearSpeedMetersPerSec(), omega * drive.getMaxAngularSpeedRadPerSec()); boolean isFlipped = - DriverStation.getAlliance().isPresent() - && DriverStation.getAlliance().get() == Alliance.Red; + DriverStationBackend.getAlliance().isPresent() + && DriverStationBackend.getAlliance().get() == Alliance.RED; drive.runVelocity( - ChassisSpeeds.fromFieldRelativeSpeeds( - speeds, + speeds.toRobotRelative( isFlipped ? drive.getRotation().plus(new Rotation2d(Math.PI)) : drive.getRotation())); @@ -130,17 +129,16 @@ public static Command joystickDriveAtAngle( drive.getRotation().getRadians(), rotationSupplier.get().getRadians()); // Convert to field relative speeds & send command - ChassisSpeeds speeds = - new ChassisSpeeds( + ChassisVelocities speeds = + new ChassisVelocities( linearVelocity.getX() * drive.getMaxLinearSpeedMetersPerSec(), linearVelocity.getY() * drive.getMaxLinearSpeedMetersPerSec(), omega); boolean isFlipped = - DriverStation.getAlliance().isPresent() - && DriverStation.getAlliance().get() == Alliance.Red; + DriverStationBackend.getAlliance().isPresent() + && DriverStationBackend.getAlliance().get() == Alliance.RED; drive.runVelocity( - ChassisSpeeds.fromFieldRelativeSpeeds( - speeds, + speeds.toRobotRelative( isFlipped ? drive.getRotation().plus(new Rotation2d(Math.PI)) : drive.getRotation())); @@ -232,7 +230,7 @@ public static Command wheelRadiusCharacterization(Drive drive) { Commands.run( () -> { double speed = limiter.calculate(WHEEL_RADIUS_MAX_VELOCITY); - drive.runVelocity(new ChassisSpeeds(0.0, 0.0, speed)); + drive.runVelocity(new ChassisVelocities(0.0, 0.0, speed)); }, drive)), diff --git a/src/main/java/frc/robot/constants/AllianceBasedFieldConstants.java b/src/main/java/frc/robot/constants/AllianceBasedFieldConstants.java index 3926253f..91d5cda7 100644 --- a/src/main/java/frc/robot/constants/AllianceBasedFieldConstants.java +++ b/src/main/java/frc/robot/constants/AllianceBasedFieldConstants.java @@ -2,10 +2,10 @@ import coppercore.wpilib_interface.alliance_util.AllianceUtil; import coppercore.wpilib_interface.alliance_util.AllianceUtil.AllianceBasedValue; -import edu.wpi.first.math.geometry.Pose2d; -import edu.wpi.first.math.geometry.Translation2d; -import edu.wpi.first.math.geometry.Translation3d; -import edu.wpi.first.wpilibj.DriverStation.Alliance; +import org.wpilib.math.geometry.Pose2d; +import org.wpilib.math.geometry.Translation2d; +import org.wpilib.math.geometry.Translation3d; +import org.wpilib.driverstation.Alliance; /** * The AllianceBasedFieldConstants class provides methods for getting relevant field locations from @@ -36,8 +36,8 @@ public static final boolean isInAllianceZone(Pose2d robotPose) { Alliance alliance = AllianceUtil.getAlliance(); return switch (alliance) { - case Red -> robotPose.getX() > FieldConstants.LinesVertical.oppAllianceZone(); - case Blue -> robotPose.getX() < FieldConstants.LinesVertical.allianceZone(); + case RED -> robotPose.getX() > FieldConstants.LinesVertical.oppAllianceZone(); + case BLUE -> robotPose.getX() < FieldConstants.LinesVertical.allianceZone(); }; } @@ -52,8 +52,8 @@ public static final boolean isInOppAllianceZone(Pose2d robotPose) { Alliance alliance = AllianceUtil.getAlliance(); return switch (alliance) { - case Red -> robotPose.getX() < FieldConstants.LinesVertical.allianceZone(); - case Blue -> robotPose.getX() > FieldConstants.LinesVertical.oppAllianceZone(); + case RED -> robotPose.getX() < FieldConstants.LinesVertical.allianceZone(); + case BLUE -> robotPose.getX() > FieldConstants.LinesVertical.oppAllianceZone(); }; } } diff --git a/src/main/java/frc/robot/constants/AprilTagConstants.java b/src/main/java/frc/robot/constants/AprilTagConstants.java index 65299861..c5258f36 100644 --- a/src/main/java/frc/robot/constants/AprilTagConstants.java +++ b/src/main/java/frc/robot/constants/AprilTagConstants.java @@ -1,8 +1,8 @@ package frc.robot.constants; import coppercore.parameter_tools.json.annotations.JSONExclude; -import edu.wpi.first.apriltag.AprilTagFieldLayout; -import edu.wpi.first.wpilibj.Filesystem; +import org.wpilib.vision.apriltag.AprilTagFieldLayout; +import org.wpilib.system.Filesystem; import java.io.IOException; import java.nio.file.Path; diff --git a/src/main/java/frc/robot/constants/ClimberConstants.java b/src/main/java/frc/robot/constants/ClimberConstants.java index 9d5a6c3d..1acf313e 100644 --- a/src/main/java/frc/robot/constants/ClimberConstants.java +++ b/src/main/java/frc/robot/constants/ClimberConstants.java @@ -1,14 +1,14 @@ package frc.robot.constants; -import static edu.wpi.first.units.Units.Amps; -import static edu.wpi.first.units.Units.Degrees; -import static edu.wpi.first.units.Units.DegreesPerSecond; -import static edu.wpi.first.units.Units.Inches; -import static edu.wpi.first.units.Units.Kilograms; -import static edu.wpi.first.units.Units.Meters; -import static edu.wpi.first.units.Units.Rotations; -import static edu.wpi.first.units.Units.Seconds; -import static edu.wpi.first.units.Units.Volts; +import static org.wpilib.units.Units.Amps; +import static org.wpilib.units.Units.Degrees; +import static org.wpilib.units.Units.DegreesPerSecond; +import static org.wpilib.units.Units.Inches; +import static org.wpilib.units.Units.Kilograms; +import static org.wpilib.units.Units.Meters; +import static org.wpilib.units.Units.Rotations; +import static org.wpilib.units.Units.Seconds; +import static org.wpilib.units.Units.Volts; import com.ctre.phoenix6.configs.CurrentLimitsConfigs; import com.ctre.phoenix6.configs.FeedbackConfigs; @@ -23,16 +23,16 @@ import coppercore.wpilib_interface.subsystems.configs.MechanismConfig.GravityFeedforwardType; import coppercore.wpilib_interface.subsystems.sim.CoppercoreSimAdapter; import coppercore.wpilib_interface.subsystems.sim.ElevatorSimAdapter; -import edu.wpi.first.math.system.plant.DCMotor; -import edu.wpi.first.math.system.plant.LinearSystemId; -import edu.wpi.first.units.measure.Angle; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.units.measure.Current; -import edu.wpi.first.units.measure.Distance; -import edu.wpi.first.units.measure.Mass; -import edu.wpi.first.units.measure.Time; -import edu.wpi.first.units.measure.Voltage; -import edu.wpi.first.wpilibj.simulation.ElevatorSim; +import org.wpilib.math.system.DCMotor; +import org.wpilib.math.system.Models; +import org.wpilib.units.measure.Angle; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.units.measure.Current; +import org.wpilib.units.measure.Distance; +import org.wpilib.units.measure.Mass; +import org.wpilib.units.measure.Time; +import org.wpilib.units.measure.Voltage; +import org.wpilib.simulation.ElevatorSim; // Copilot was used to help write this file public class ClimberConstants { @@ -136,7 +136,7 @@ public CoppercoreSimAdapter buildClimberSim() { return new ElevatorSimAdapter( buildMechanismConfig(), new ElevatorSim( - LinearSystemId.createElevatorSystem( + Models.elevatorFromPhysicalConstants( DCMotor.getKrakenX60Foc(1), simClimberWeight.in(Kilograms), simClimberRadius.in(Meters), diff --git a/src/main/java/frc/robot/constants/FieldConstants.java b/src/main/java/frc/robot/constants/FieldConstants.java index 12101007..9bfdd32a 100644 --- a/src/main/java/frc/robot/constants/FieldConstants.java +++ b/src/main/java/frc/robot/constants/FieldConstants.java @@ -12,10 +12,10 @@ package frc.robot.constants; -import edu.wpi.first.math.geometry.Pose2d; -import edu.wpi.first.math.geometry.Translation2d; -import edu.wpi.first.math.geometry.Translation3d; -import edu.wpi.first.math.util.Units; +import org.wpilib.math.geometry.Pose2d; +import org.wpilib.math.geometry.Translation2d; +import org.wpilib.math.geometry.Translation3d; +import org.wpilib.math.util.Units; // TODO: Replace "opp" references with a good way to get constants for whatever alliance we're on diff --git a/src/main/java/frc/robot/constants/FieldLocationInstance.java b/src/main/java/frc/robot/constants/FieldLocationInstance.java index 07d223c0..ab399310 100644 --- a/src/main/java/frc/robot/constants/FieldLocationInstance.java +++ b/src/main/java/frc/robot/constants/FieldLocationInstance.java @@ -1,6 +1,6 @@ package frc.robot.constants; -import edu.wpi.first.math.geometry.Translation2d; +import org.wpilib.math.geometry.Translation2d; /** * Contains "field locations" (e.g. passing targets, locations for autonomous or semi-autonomous diff --git a/src/main/java/frc/robot/constants/FieldLocations.java b/src/main/java/frc/robot/constants/FieldLocations.java index dcc63135..3c13e544 100644 --- a/src/main/java/frc/robot/constants/FieldLocations.java +++ b/src/main/java/frc/robot/constants/FieldLocations.java @@ -1,7 +1,7 @@ package frc.robot.constants; import coppercore.wpilib_interface.alliance_util.AllianceUtil; -import edu.wpi.first.math.geometry.Translation2d; +import org.wpilib.math.geometry.Translation2d; /** * The FieldLocations class provides static methods to get field locations for the current alliance. diff --git a/src/main/java/frc/robot/constants/HoodConstants.java b/src/main/java/frc/robot/constants/HoodConstants.java index 2e90cbfd..cdaaf790 100644 --- a/src/main/java/frc/robot/constants/HoodConstants.java +++ b/src/main/java/frc/robot/constants/HoodConstants.java @@ -1,16 +1,16 @@ package frc.robot.constants; -import static edu.wpi.first.units.Units.Amps; -import static edu.wpi.first.units.Units.Degrees; -import static edu.wpi.first.units.Units.DegreesPerSecond; -import static edu.wpi.first.units.Units.Hertz; -import static edu.wpi.first.units.Units.Inches; -import static edu.wpi.first.units.Units.KilogramSquareMeters; -import static edu.wpi.first.units.Units.Meters; -import static edu.wpi.first.units.Units.MetersPerSecond; -import static edu.wpi.first.units.Units.Radians; -import static edu.wpi.first.units.Units.Seconds; -import static edu.wpi.first.units.Units.Volts; +import static org.wpilib.units.Units.Amps; +import static org.wpilib.units.Units.Degrees; +import static org.wpilib.units.Units.DegreesPerSecond; +import static org.wpilib.units.Units.Hertz; +import static org.wpilib.units.Units.Inches; +import static org.wpilib.units.Units.KilogramSquareMeters; +import static org.wpilib.units.Units.Meters; +import static org.wpilib.units.Units.MetersPerSecond; +import static org.wpilib.units.Units.Radians; +import static org.wpilib.units.Units.Seconds; +import static org.wpilib.units.Units.Volts; import com.ctre.phoenix6.configs.CurrentLimitsConfigs; import com.ctre.phoenix6.configs.FeedbackConfigs; @@ -26,17 +26,17 @@ import coppercore.wpilib_interface.subsystems.configs.MechanismConfig.GravityFeedforwardType; import coppercore.wpilib_interface.subsystems.sim.ArmSimAdapter; import coppercore.wpilib_interface.subsystems.sim.CoppercoreSimAdapter; -import edu.wpi.first.math.system.plant.DCMotor; -import edu.wpi.first.units.measure.Angle; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.units.measure.Current; -import edu.wpi.first.units.measure.Distance; -import edu.wpi.first.units.measure.Frequency; -import edu.wpi.first.units.measure.LinearVelocity; -import edu.wpi.first.units.measure.MomentOfInertia; -import edu.wpi.first.units.measure.Time; -import edu.wpi.first.units.measure.Voltage; -import edu.wpi.first.wpilibj.simulation.SingleJointedArmSim; +import org.wpilib.math.system.DCMotor; +import org.wpilib.units.measure.Angle; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.units.measure.Current; +import org.wpilib.units.measure.Distance; +import org.wpilib.units.measure.Frequency; +import org.wpilib.units.measure.LinearVelocity; +import org.wpilib.units.measure.MomentOfInertia; +import org.wpilib.units.measure.Time; +import org.wpilib.units.measure.Voltage; +import org.wpilib.simulation.SingleJointedArmSim; import frc.robot.Constants; import frc.robot.Constants.Mode; diff --git a/src/main/java/frc/robot/constants/HopperConstants.java b/src/main/java/frc/robot/constants/HopperConstants.java index b15cde9f..e79f1d08 100644 --- a/src/main/java/frc/robot/constants/HopperConstants.java +++ b/src/main/java/frc/robot/constants/HopperConstants.java @@ -1,14 +1,14 @@ package frc.robot.constants; -import static edu.wpi.first.units.Units.Amps; -// import static edu.wpi.first.units.Units.DegreesPerSecond; -import static edu.wpi.first.units.Units.KilogramSquareMeters; -import static edu.wpi.first.units.Units.RPM; -import static edu.wpi.first.units.Units.RadiansPerSecond; -import static edu.wpi.first.units.Units.RotationsPerSecond; -import static edu.wpi.first.units.Units.RotationsPerSecondPerSecond; -import static edu.wpi.first.units.Units.Seconds; -import static edu.wpi.first.units.Units.Volts; +import static org.wpilib.units.Units.Amps; +// import static org.wpilib.units.Units.DegreesPerSecond; +import static org.wpilib.units.Units.KilogramSquareMeters; +import static org.wpilib.units.Units.RPM; +import static org.wpilib.units.Units.RadiansPerSecond; +import static org.wpilib.units.Units.RotationsPerSecond; +import static org.wpilib.units.Units.RotationsPerSecondPerSecond; +import static org.wpilib.units.Units.Seconds; +import static org.wpilib.units.Units.Volts; import com.ctre.phoenix6.configs.CurrentLimitsConfigs; import com.ctre.phoenix6.configs.MotorOutputConfigs; @@ -19,16 +19,16 @@ import coppercore.wpilib_interface.subsystems.configs.MechanismConfig.GravityFeedforwardType; import coppercore.wpilib_interface.subsystems.motors.profile.MotionProfileConfig; import coppercore.wpilib_interface.subsystems.sim.CoppercoreSimAdapter; -import coppercore.wpilib_interface.subsystems.sim.DCMotorSimAdapter; +import coppercore.wpilib_interface.subsystems.sim.FlywheelSimAdapter; import coppercore.wpilib_interface.tuning.PIDGains; -import edu.wpi.first.math.system.plant.DCMotor; -import edu.wpi.first.math.system.plant.LinearSystemId; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.units.measure.Current; -import edu.wpi.first.units.measure.MomentOfInertia; -import edu.wpi.first.units.measure.Time; -import edu.wpi.first.units.measure.Voltage; -import edu.wpi.first.wpilibj.simulation.DCMotorSim; +import org.wpilib.math.system.DCMotor; +import org.wpilib.math.system.Models; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.units.measure.Current; +import org.wpilib.units.measure.MomentOfInertia; +import org.wpilib.units.measure.Time; +import org.wpilib.units.measure.Voltage; +import org.wpilib.simulation.FlywheelSim; public class HopperConstants { @@ -99,10 +99,10 @@ public TalonFXConfiguration buildTalonFXConfigs() { } public CoppercoreSimAdapter buildHopperSim() { - return new DCMotorSimAdapter( + return new FlywheelSimAdapter( buildMechanismConfig(), - new DCMotorSim( - LinearSystemId.createDCMotorSystem( + new FlywheelSim( + Models.flywheelFromPhysicalConstants( DCMotor.getKrakenX60(1), simHopperMOI.in(KilogramSquareMeters), 1 / hopperReduction), diff --git a/src/main/java/frc/robot/constants/IndexerConstants.java b/src/main/java/frc/robot/constants/IndexerConstants.java index 25e3b462..346af71b 100644 --- a/src/main/java/frc/robot/constants/IndexerConstants.java +++ b/src/main/java/frc/robot/constants/IndexerConstants.java @@ -1,12 +1,12 @@ package frc.robot.constants; -import static edu.wpi.first.units.Units.Amps; -import static edu.wpi.first.units.Units.KilogramSquareMeters; -import static edu.wpi.first.units.Units.RPM; -import static edu.wpi.first.units.Units.RotationsPerSecond; -import static edu.wpi.first.units.Units.RotationsPerSecondPerSecond; -import static edu.wpi.first.units.Units.Seconds; -import static edu.wpi.first.units.Units.Volts; +import static org.wpilib.units.Units.Amps; +import static org.wpilib.units.Units.KilogramSquareMeters; +import static org.wpilib.units.Units.RPM; +import static org.wpilib.units.Units.RotationsPerSecond; +import static org.wpilib.units.Units.RotationsPerSecondPerSecond; +import static org.wpilib.units.Units.Seconds; +import static org.wpilib.units.Units.Volts; import com.ctre.phoenix6.configs.CurrentLimitsConfigs; import com.ctre.phoenix6.configs.FeedbackConfigs; @@ -18,15 +18,15 @@ import coppercore.wpilib_interface.subsystems.configs.MechanismConfig.GravityFeedforwardType; import coppercore.wpilib_interface.subsystems.motors.profile.MotionProfileConfig; import coppercore.wpilib_interface.subsystems.sim.CoppercoreSimAdapter; -import coppercore.wpilib_interface.subsystems.sim.DCMotorSimAdapter; +import coppercore.wpilib_interface.subsystems.sim.FlywheelSimAdapter; import coppercore.wpilib_interface.tuning.PIDGains; -import edu.wpi.first.math.system.plant.DCMotor; -import edu.wpi.first.math.system.plant.LinearSystemId; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.units.measure.Current; -import edu.wpi.first.units.measure.MomentOfInertia; -import edu.wpi.first.units.measure.Time; -import edu.wpi.first.wpilibj.simulation.DCMotorSim; +import org.wpilib.math.system.DCMotor; +import org.wpilib.math.system.Models; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.units.measure.Current; +import org.wpilib.units.measure.MomentOfInertia; +import org.wpilib.units.measure.Time; +import org.wpilib.simulation.FlywheelSim; public class IndexerConstants { @@ -87,10 +87,10 @@ public TalonFXConfiguration buildTalonFXConfigs() { } public CoppercoreSimAdapter buildIndexerSim() { - return new DCMotorSimAdapter( + return new FlywheelSimAdapter( buildMechanismConfig(), - new DCMotorSim( - LinearSystemId.createDCMotorSystem( + new FlywheelSim( + Models.flywheelFromPhysicalConstants( DCMotor.getKrakenX44Foc(1), simIndexerMOI.in(KilogramSquareMeters), 1 / indexerReduction), diff --git a/src/main/java/frc/robot/constants/IntakeConstants.java b/src/main/java/frc/robot/constants/IntakeConstants.java index 64c0f2d3..cdb76474 100644 --- a/src/main/java/frc/robot/constants/IntakeConstants.java +++ b/src/main/java/frc/robot/constants/IntakeConstants.java @@ -1,14 +1,14 @@ package frc.robot.constants; -import static edu.wpi.first.units.Units.Amps; -import static edu.wpi.first.units.Units.Degrees; -import static edu.wpi.first.units.Units.KilogramSquareMeters; -import static edu.wpi.first.units.Units.Meters; -import static edu.wpi.first.units.Units.RPM; -import static edu.wpi.first.units.Units.Radians; -import static edu.wpi.first.units.Units.RadiansPerSecond; -import static edu.wpi.first.units.Units.Seconds; -import static edu.wpi.first.units.Units.Volts; +import static org.wpilib.units.Units.Amps; +import static org.wpilib.units.Units.Degrees; +import static org.wpilib.units.Units.KilogramSquareMeters; +import static org.wpilib.units.Units.Meters; +import static org.wpilib.units.Units.RPM; +import static org.wpilib.units.Units.Radians; +import static org.wpilib.units.Units.RadiansPerSecond; +import static org.wpilib.units.Units.Seconds; +import static org.wpilib.units.Units.Volts; import com.ctre.phoenix6.configs.CurrentLimitsConfigs; import com.ctre.phoenix6.configs.FeedbackConfigs; @@ -25,21 +25,21 @@ import coppercore.wpilib_interface.subsystems.configs.MechanismConfig.GravityFeedforwardType; import coppercore.wpilib_interface.subsystems.sim.ArmSimAdapter; import coppercore.wpilib_interface.subsystems.sim.CoppercoreSimAdapter; -import coppercore.wpilib_interface.subsystems.sim.DCMotorSimAdapter; +import coppercore.wpilib_interface.subsystems.sim.FlywheelSimAdapter; import coppercore.wpilib_interface.tuning.PIDGains; -import edu.wpi.first.math.system.plant.DCMotor; -import edu.wpi.first.math.system.plant.LinearSystemId; -import edu.wpi.first.units.Units; -import edu.wpi.first.units.measure.Angle; -import edu.wpi.first.units.measure.AngularAcceleration; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.units.measure.Current; -import edu.wpi.first.units.measure.Distance; -import edu.wpi.first.units.measure.MomentOfInertia; -import edu.wpi.first.units.measure.Time; -import edu.wpi.first.units.measure.Voltage; -import edu.wpi.first.wpilibj.simulation.DCMotorSim; -import edu.wpi.first.wpilibj.simulation.SingleJointedArmSim; +import org.wpilib.math.system.DCMotor; +import org.wpilib.math.system.Models; +import org.wpilib.units.Units; +import org.wpilib.units.measure.Angle; +import org.wpilib.units.measure.AngularAcceleration; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.units.measure.Current; +import org.wpilib.units.measure.Distance; +import org.wpilib.units.measure.MomentOfInertia; +import org.wpilib.units.measure.Time; +import org.wpilib.units.measure.Voltage; +import org.wpilib.simulation.FlywheelSim; +import org.wpilib.simulation.SingleJointedArmSim; public class IntakeConstants { @@ -193,10 +193,10 @@ public MechanismConfig buildRollersMechanismConfig() { public CoppercoreSimAdapter buildRollersSim() { DCMotor motor = DCMotor.getKrakenX60Foc(2); - return new DCMotorSimAdapter( + return new FlywheelSimAdapter( buildRollersMechanismConfig(), - new DCMotorSim( - LinearSystemId.createDCMotorSystem(motor, rollersInertia.in(KilogramSquareMeters), 1.0), + new FlywheelSim( + Models.flywheelFromPhysicalConstants(motor, rollersInertia.in(KilogramSquareMeters), 1.0), motor)); } } diff --git a/src/main/java/frc/robot/constants/JsonConstants.java b/src/main/java/frc/robot/constants/JsonConstants.java index 097adc97..8eaa5aa5 100644 --- a/src/main/java/frc/robot/constants/JsonConstants.java +++ b/src/main/java/frc/robot/constants/JsonConstants.java @@ -1,9 +1,9 @@ package frc.robot.constants; -import static edu.wpi.first.units.Units.Amp; -import static edu.wpi.first.units.Units.RPM; -import static edu.wpi.first.units.Units.RotationsPerSecondPerSecond; -import static edu.wpi.first.units.Units.Second; +import static org.wpilib.units.Units.Amp; +import static org.wpilib.units.Units.RPM; +import static org.wpilib.units.Units.RotationsPerSecondPerSecond; +import static org.wpilib.units.Units.Second; import com.therekrab.autopilot.APTarget; import coppercore.parameter_tools.json.JSONHandler; @@ -18,11 +18,11 @@ import coppercore.parameter_tools.path_provider.EnvironmentHandler; import coppercore.wpilib_interface.controllers.Controllers; import coppercore.wpilib_interface.subsystems.motors.profile.MotionProfileConfig; -import edu.wpi.first.math.geometry.Rotation2d; -import edu.wpi.first.math.geometry.Rotation3d; -import edu.wpi.first.math.geometry.Transform2d; -import edu.wpi.first.math.geometry.Transform3d; -import edu.wpi.first.wpilibj.Filesystem; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.math.geometry.Rotation3d; +import org.wpilib.math.geometry.Transform2d; +import org.wpilib.math.geometry.Transform3d; +import org.wpilib.system.Filesystem; import frc.robot.RobotContainer; import frc.robot.auto.Autos; import frc.robot.constants.drive.DriveConstants; diff --git a/src/main/java/frc/robot/constants/ManualModeConstants.java b/src/main/java/frc/robot/constants/ManualModeConstants.java index c9f174f4..f81dfe07 100644 --- a/src/main/java/frc/robot/constants/ManualModeConstants.java +++ b/src/main/java/frc/robot/constants/ManualModeConstants.java @@ -1,9 +1,9 @@ package frc.robot.constants; -import static edu.wpi.first.units.Units.Meters; +import static org.wpilib.units.Units.Meters; -import edu.wpi.first.math.geometry.Rotation2d; -import edu.wpi.first.units.measure.Distance; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.units.measure.Distance; /** ManualModeConstants contains constants that define how to shoot when vision isn't used */ public class ManualModeConstants { diff --git a/src/main/java/frc/robot/constants/RobotInfo.java b/src/main/java/frc/robot/constants/RobotInfo.java index b4012993..ac7e6640 100644 --- a/src/main/java/frc/robot/constants/RobotInfo.java +++ b/src/main/java/frc/robot/constants/RobotInfo.java @@ -1,9 +1,9 @@ package frc.robot.constants; -import static edu.wpi.first.units.Units.Hertz; -import static edu.wpi.first.units.Units.KilogramSquareMeters; -import static edu.wpi.first.units.Units.Kilograms; -import static edu.wpi.first.units.Units.Seconds; +import static org.wpilib.units.Units.Hertz; +import static org.wpilib.units.Units.KilogramSquareMeters; +import static org.wpilib.units.Units.Kilograms; +import static org.wpilib.units.Units.Seconds; import com.ctre.phoenix6.CANBus; import com.ctre.phoenix6.configs.CANdiConfiguration; @@ -16,13 +16,13 @@ import coppercore.parameter_tools.json.annotations.JSONExclude; import coppercore.wpilib_interface.subsystems.dio_switch.DigitalInputIOCANdi.CANdiSignal; import coppercore.wpilib_interface.subsystems.motors.talonfx.MotorIOTalonFX.SignalRefreshRates; -import edu.wpi.first.math.geometry.Rotation3d; -import edu.wpi.first.math.geometry.Transform2d; -import edu.wpi.first.math.geometry.Transform3d; -import edu.wpi.first.math.util.Units; -import edu.wpi.first.units.measure.Mass; -import edu.wpi.first.units.measure.MomentOfInertia; -import edu.wpi.first.units.measure.Time; +import org.wpilib.math.geometry.Rotation3d; +import org.wpilib.math.geometry.Transform2d; +import org.wpilib.math.geometry.Transform3d; +import org.wpilib.math.util.Units; +import org.wpilib.units.measure.Mass; +import org.wpilib.units.measure.MomentOfInertia; +import org.wpilib.units.measure.Time; public class RobotInfo { diff --git a/src/main/java/frc/robot/constants/ShooterConstants.java b/src/main/java/frc/robot/constants/ShooterConstants.java index 01f1c8d3..a0d952aa 100644 --- a/src/main/java/frc/robot/constants/ShooterConstants.java +++ b/src/main/java/frc/robot/constants/ShooterConstants.java @@ -1,12 +1,12 @@ package frc.robot.constants; -import static edu.wpi.first.units.Units.Amps; -import static edu.wpi.first.units.Units.Hertz; -import static edu.wpi.first.units.Units.KilogramSquareMeters; -import static edu.wpi.first.units.Units.RPM; -import static edu.wpi.first.units.Units.Second; -import static edu.wpi.first.units.Units.Seconds; -import static edu.wpi.first.units.Units.Volts; +import static org.wpilib.units.Units.Amps; +import static org.wpilib.units.Units.Hertz; +import static org.wpilib.units.Units.KilogramSquareMeters; +import static org.wpilib.units.Units.RPM; +import static org.wpilib.units.Units.Second; +import static org.wpilib.units.Units.Seconds; +import static org.wpilib.units.Units.Volts; import com.ctre.phoenix6.CANBus; import com.ctre.phoenix6.configs.ClosedLoopRampsConfigs; @@ -29,18 +29,18 @@ import coppercore.wpilib_interface.subsystems.sim.CoppercoreSimAdapter; import coppercore.wpilib_interface.subsystems.sim.FlywheelSimAdapter; import coppercore.wpilib_interface.tuning.PIDGains; -import edu.wpi.first.math.interpolation.InterpolatingDoubleTreeMap; -import edu.wpi.first.math.system.plant.DCMotor; -import edu.wpi.first.math.system.plant.LinearSystemId; -import edu.wpi.first.units.VoltageUnit; -import edu.wpi.first.units.measure.AngularAcceleration; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.units.measure.Current; -import edu.wpi.first.units.measure.Frequency; -import edu.wpi.first.units.measure.MomentOfInertia; -import edu.wpi.first.units.measure.Time; -import edu.wpi.first.units.measure.Velocity; -import edu.wpi.first.wpilibj.simulation.FlywheelSim; +import org.wpilib.math.interpolation.InterpolatingDoubleTreeMap; +import org.wpilib.math.system.DCMotor; +import org.wpilib.math.system.Models; +import org.wpilib.units.VoltageUnit; +import org.wpilib.units.measure.AngularAcceleration; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.units.measure.Current; +import org.wpilib.units.measure.Frequency; +import org.wpilib.units.measure.MomentOfInertia; +import org.wpilib.units.measure.Time; +import org.wpilib.units.measure.Velocity; +import org.wpilib.simulation.FlywheelSim; public class ShooterConstants { public final Double[] distanceToViDistancesMeters = {1.8, 2.0, 3.5}; @@ -212,7 +212,7 @@ public CoppercoreSimAdapter buildShooterSim() { return new FlywheelSimAdapter( buildMechanismConfig(), new FlywheelSim( - LinearSystemId.createFlywheelSystem( + Models.flywheelFromPhysicalConstants( DCMotor.getKrakenX60Foc(3), shooterMOI.in(KilogramSquareMeters), 1.0), DCMotor.getKrakenX60Foc(3))); } diff --git a/src/main/java/frc/robot/constants/ShotMaps.java b/src/main/java/frc/robot/constants/ShotMaps.java index 9f6597d8..53da2e0e 100644 --- a/src/main/java/frc/robot/constants/ShotMaps.java +++ b/src/main/java/frc/robot/constants/ShotMaps.java @@ -1,22 +1,22 @@ package frc.robot.constants; -import static edu.wpi.first.units.Units.Degrees; -import static edu.wpi.first.units.Units.Meters; -import static edu.wpi.first.units.Units.RPM; -import static edu.wpi.first.units.Units.Radians; -import static edu.wpi.first.units.Units.Seconds; +import static org.wpilib.units.Units.Degrees; +import static org.wpilib.units.Units.Meters; +import static org.wpilib.units.Units.RPM; +import static org.wpilib.units.Units.Radians; +import static org.wpilib.units.Units.Seconds; import coppercore.parameter_tools.LoggedTunableNumber; import coppercore.parameter_tools.json.annotations.AfterJsonLoad; import coppercore.parameter_tools.json.annotations.JSONExclude; -import edu.wpi.first.math.interpolation.InterpolatingDoubleTreeMap; -import edu.wpi.first.units.measure.Angle; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.units.measure.Distance; -import edu.wpi.first.units.measure.Time; -import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; -import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.InstantCommand; +import org.wpilib.math.interpolation.InterpolatingDoubleTreeMap; +import org.wpilib.units.measure.Angle; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.units.measure.Distance; +import org.wpilib.units.measure.Time; +import org.wpilib.smartdashboard.SmartDashboard; +import org.wpilib.command2.Command; +import org.wpilib.command2.InstantCommand; import java.util.Arrays; import java.util.Comparator; import java.util.function.Function; diff --git a/src/main/java/frc/robot/constants/StrategyConstants.java b/src/main/java/frc/robot/constants/StrategyConstants.java index 2f25eca1..3661a031 100644 --- a/src/main/java/frc/robot/constants/StrategyConstants.java +++ b/src/main/java/frc/robot/constants/StrategyConstants.java @@ -1,8 +1,8 @@ package frc.robot.constants; -import static edu.wpi.first.units.Units.Seconds; +import static org.wpilib.units.Units.Seconds; -import edu.wpi.first.units.measure.Time; +import org.wpilib.units.measure.Time; public class StrategyConstants { // Due to the presence of these constants, it is necessary for the driver(s) to play an active diff --git a/src/main/java/frc/robot/constants/TransferRollerConstants.java b/src/main/java/frc/robot/constants/TransferRollerConstants.java index 4d67b3f4..e8f1c1c7 100644 --- a/src/main/java/frc/robot/constants/TransferRollerConstants.java +++ b/src/main/java/frc/robot/constants/TransferRollerConstants.java @@ -1,12 +1,12 @@ package frc.robot.constants; -import static edu.wpi.first.units.Units.Amps; -import static edu.wpi.first.units.Units.KilogramSquareMeters; -import static edu.wpi.first.units.Units.RPM; -import static edu.wpi.first.units.Units.RotationsPerSecond; -import static edu.wpi.first.units.Units.RotationsPerSecondPerSecond; -import static edu.wpi.first.units.Units.Seconds; -import static edu.wpi.first.units.Units.Volts; +import static org.wpilib.units.Units.Amps; +import static org.wpilib.units.Units.KilogramSquareMeters; +import static org.wpilib.units.Units.RPM; +import static org.wpilib.units.Units.RotationsPerSecond; +import static org.wpilib.units.Units.RotationsPerSecondPerSecond; +import static org.wpilib.units.Units.Seconds; +import static org.wpilib.units.Units.Volts; import com.ctre.phoenix6.configs.CurrentLimitsConfigs; import com.ctre.phoenix6.configs.FeedbackConfigs; @@ -18,15 +18,15 @@ import coppercore.wpilib_interface.subsystems.configs.MechanismConfig.GravityFeedforwardType; import coppercore.wpilib_interface.subsystems.motors.profile.MotionProfileConfig; import coppercore.wpilib_interface.subsystems.sim.CoppercoreSimAdapter; -import coppercore.wpilib_interface.subsystems.sim.DCMotorSimAdapter; +import coppercore.wpilib_interface.subsystems.sim.FlywheelSimAdapter; import coppercore.wpilib_interface.tuning.PIDGains; -import edu.wpi.first.math.system.plant.DCMotor; -import edu.wpi.first.math.system.plant.LinearSystemId; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.units.measure.Current; -import edu.wpi.first.units.measure.MomentOfInertia; -import edu.wpi.first.units.measure.Time; -import edu.wpi.first.wpilibj.simulation.DCMotorSim; +import org.wpilib.math.system.DCMotor; +import org.wpilib.math.system.Models; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.units.measure.Current; +import org.wpilib.units.measure.MomentOfInertia; +import org.wpilib.units.measure.Time; +import org.wpilib.simulation.FlywheelSim; public class TransferRollerConstants { @@ -85,10 +85,10 @@ public TalonFXConfiguration buildTalonFXConfigs() { } public CoppercoreSimAdapter buildTransferRollerSim() { - return new DCMotorSimAdapter( + return new FlywheelSimAdapter( buildMechanismConfig(), - new DCMotorSim( - LinearSystemId.createDCMotorSystem( + new FlywheelSim( + Models.flywheelFromPhysicalConstants( DCMotor.getKrakenX44Foc(1), simTransferRollerMOI.in(KilogramSquareMeters), 1 / transferRollerReduction), diff --git a/src/main/java/frc/robot/constants/TurretConstants.java b/src/main/java/frc/robot/constants/TurretConstants.java index cf1eb719..e8a82fc2 100644 --- a/src/main/java/frc/robot/constants/TurretConstants.java +++ b/src/main/java/frc/robot/constants/TurretConstants.java @@ -1,11 +1,11 @@ package frc.robot.constants; -import static edu.wpi.first.units.Units.Amps; -import static edu.wpi.first.units.Units.Degrees; -import static edu.wpi.first.units.Units.DegreesPerSecond; -import static edu.wpi.first.units.Units.KilogramSquareMeters; -import static edu.wpi.first.units.Units.Seconds; -import static edu.wpi.first.units.Units.Volts; +import static org.wpilib.units.Units.Amps; +import static org.wpilib.units.Units.Degrees; +import static org.wpilib.units.Units.DegreesPerSecond; +import static org.wpilib.units.Units.KilogramSquareMeters; +import static org.wpilib.units.Units.Seconds; +import static org.wpilib.units.Units.Volts; import com.ctre.phoenix6.configs.AudioConfigs; import com.ctre.phoenix6.configs.CurrentLimitsConfigs; @@ -24,15 +24,15 @@ import coppercore.wpilib_interface.subsystems.configs.MechanismConfig.GravityFeedforwardType; import coppercore.wpilib_interface.subsystems.sim.CoppercoreSimAdapter; import coppercore.wpilib_interface.subsystems.sim.HardstoppedDCMotorSimAdapter; -import edu.wpi.first.math.system.plant.DCMotor; -import edu.wpi.first.math.system.plant.LinearSystemId; -import edu.wpi.first.units.measure.Angle; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.units.measure.Current; -import edu.wpi.first.units.measure.MomentOfInertia; -import edu.wpi.first.units.measure.Time; -import edu.wpi.first.units.measure.Voltage; -import edu.wpi.first.wpilibj.simulation.DCMotorSim; +import org.wpilib.math.system.DCMotor; +import org.wpilib.math.system.Models; +import org.wpilib.units.measure.Angle; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.units.measure.Current; +import org.wpilib.units.measure.MomentOfInertia; +import org.wpilib.units.measure.Time; +import org.wpilib.units.measure.Voltage; +import org.wpilib.simulation.DCMotorSim; public class TurretConstants { public final Boolean wearInTurret = false; @@ -163,7 +163,7 @@ public CoppercoreSimAdapter buildTurretSim() { return new HardstoppedDCMotorSimAdapter( buildMechanismConfig(), new DCMotorSim( - LinearSystemId.createDCMotorSystem( + Models.singleJointedArmFromPhysicalConstants( DCMotor.getKrakenX44Foc(1), simTurretMOI.in(KilogramSquareMeters), 1 / turretReduction), diff --git a/src/main/java/frc/robot/constants/VisionConstants.java b/src/main/java/frc/robot/constants/VisionConstants.java index a720d891..edd3ada4 100644 --- a/src/main/java/frc/robot/constants/VisionConstants.java +++ b/src/main/java/frc/robot/constants/VisionConstants.java @@ -1,12 +1,12 @@ package frc.robot.constants; -import static edu.wpi.first.units.Units.Seconds; +import static org.wpilib.units.Units.Seconds; import coppercore.vision.VisionGainConstants; -import edu.wpi.first.math.geometry.Rotation3d; -import edu.wpi.first.math.geometry.Transform3d; -import edu.wpi.first.math.util.Units; -import edu.wpi.first.units.measure.Time; +import org.wpilib.math.geometry.Rotation3d; +import org.wpilib.math.geometry.Transform3d; +import org.wpilib.math.util.Units; +import org.wpilib.units.measure.Time; public class VisionConstants { // Placeholder values for camera configs diff --git a/src/main/java/frc/robot/constants/drive/DriveConstants.java b/src/main/java/frc/robot/constants/drive/DriveConstants.java index 0f19d629..ca68defc 100644 --- a/src/main/java/frc/robot/constants/drive/DriveConstants.java +++ b/src/main/java/frc/robot/constants/drive/DriveConstants.java @@ -1,19 +1,19 @@ package frc.robot.constants.drive; -import static edu.wpi.first.units.Units.Degrees; -import static edu.wpi.first.units.Units.Meters; -import static edu.wpi.first.units.Units.MetersPerSecond; -import static edu.wpi.first.units.Units.MetersPerSecondPerSecond; -import static edu.wpi.first.units.Units.RadiansPerSecond; -import static edu.wpi.first.units.Units.RadiansPerSecondPerSecond; +import static org.wpilib.units.Units.Degrees; +import static org.wpilib.units.Units.Meters; +import static org.wpilib.units.Units.MetersPerSecond; +import static org.wpilib.units.Units.MetersPerSecondPerSecond; +import static org.wpilib.units.Units.RadiansPerSecond; +import static org.wpilib.units.Units.RadiansPerSecondPerSecond; import coppercore.wpilib_interface.tuning.PIDGains; -import edu.wpi.first.units.measure.Angle; -import edu.wpi.first.units.measure.AngularAcceleration; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.units.measure.Distance; -import edu.wpi.first.units.measure.LinearAcceleration; -import edu.wpi.first.units.measure.LinearVelocity; +import org.wpilib.units.measure.Angle; +import org.wpilib.units.measure.AngularAcceleration; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.units.measure.Distance; +import org.wpilib.units.measure.LinearAcceleration; +import org.wpilib.units.measure.LinearVelocity; /** * Constants for the drivetrain subsystem related to driving performance and control. diff --git a/src/main/java/frc/robot/constants/drive/ModuleConfig.java b/src/main/java/frc/robot/constants/drive/ModuleConfig.java index 37d1a440..d35e91f6 100644 --- a/src/main/java/frc/robot/constants/drive/ModuleConfig.java +++ b/src/main/java/frc/robot/constants/drive/ModuleConfig.java @@ -5,8 +5,8 @@ import com.ctre.phoenix6.swerve.SwerveModuleConstants; import com.ctre.phoenix6.swerve.SwerveModuleConstantsFactory; import coppercore.parameter_tools.json.annotations.JSONExclude; -import edu.wpi.first.units.measure.Angle; -import edu.wpi.first.units.measure.Distance; +import org.wpilib.units.measure.Angle; +import org.wpilib.units.measure.Distance; public class ModuleConfig { @JSONExclude public Integer driveMotorId; diff --git a/src/main/java/frc/robot/constants/drive/PhysicalDriveConstants.java b/src/main/java/frc/robot/constants/drive/PhysicalDriveConstants.java index 8bf9c0f7..7bed9728 100644 --- a/src/main/java/frc/robot/constants/drive/PhysicalDriveConstants.java +++ b/src/main/java/frc/robot/constants/drive/PhysicalDriveConstants.java @@ -1,11 +1,11 @@ package frc.robot.constants.drive; -import static edu.wpi.first.units.Units.Amps; -import static edu.wpi.first.units.Units.Inches; -import static edu.wpi.first.units.Units.KilogramSquareMeters; -import static edu.wpi.first.units.Units.MetersPerSecond; -import static edu.wpi.first.units.Units.Rotations; -import static edu.wpi.first.units.Units.Volts; +import static org.wpilib.units.Units.Amps; +import static org.wpilib.units.Units.Inches; +import static org.wpilib.units.Units.KilogramSquareMeters; +import static org.wpilib.units.Units.MetersPerSecond; +import static org.wpilib.units.Units.Rotations; +import static org.wpilib.units.Units.Volts; import com.ctre.phoenix6.configs.CANcoderConfiguration; import com.ctre.phoenix6.configs.CurrentLimitsConfigs; @@ -22,11 +22,11 @@ import com.ctre.phoenix6.swerve.SwerveModuleConstantsFactory; import coppercore.parameter_tools.json.annotations.AfterJsonLoad; import coppercore.parameter_tools.json.annotations.JSONExclude; -import edu.wpi.first.units.measure.Current; -import edu.wpi.first.units.measure.Distance; -import edu.wpi.first.units.measure.LinearVelocity; -import edu.wpi.first.units.measure.MomentOfInertia; -import edu.wpi.first.units.measure.Voltage; +import org.wpilib.units.measure.Current; +import org.wpilib.units.measure.Distance; +import org.wpilib.units.measure.LinearVelocity; +import org.wpilib.units.measure.MomentOfInertia; +import org.wpilib.units.measure.Voltage; import frc.robot.constants.JsonConstants; import java.util.function.Supplier; diff --git a/src/main/java/frc/robot/coordination/MatchState.java b/src/main/java/frc/robot/coordination/MatchState.java index 9186ff1f..41d26d3c 100644 --- a/src/main/java/frc/robot/coordination/MatchState.java +++ b/src/main/java/frc/robot/coordination/MatchState.java @@ -1,14 +1,14 @@ package frc.robot.coordination; -import static edu.wpi.first.units.Units.Seconds; +import static org.wpilib.units.Units.Seconds; import coppercore.wpilib_interface.alliance_util.AllianceUtil; -import edu.wpi.first.wpilibj.DriverStation; -import edu.wpi.first.wpilibj.DriverStation.Alliance; -import edu.wpi.first.wpilibj.DriverStation.MatchType; -import edu.wpi.first.wpilibj.Timer; -import edu.wpi.first.wpilibj.simulation.DriverStationSim; -import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; +import org.wpilib.driverstation.Alliance; +import org.wpilib.driverstation.MatchType; +import org.wpilib.driverstation.internal.DriverStationBackend; +import org.wpilib.system.Timer; +import org.wpilib.simulation.DriverStationSim; +import org.wpilib.smartdashboard.SmartDashboard; import frc.robot.Constants; import frc.robot.Constants.Mode; import frc.robot.constants.JsonConstants; @@ -47,7 +47,7 @@ public class MatchState { */ @AutoLogOutput(key = "MatchState/isInMatch") public boolean isInMatch() { - Logger.recordOutput("MatchState/matchType", DriverStation.getMatchType()); + Logger.recordOutput("MatchState/matchType", DriverStationBackend.getMatchType()); // Hardcode true for shop testing; getMatchType doesn't return a correct value here return true; // || DriverStation.getMatchType() == DriverStation.MatchType.Practice @@ -130,7 +130,7 @@ public MatchState() { matchTypeChooser = new LoggedDashboardChooser<>("MatchState/MatchType"); for (var matchType : MatchType.values()) { - if (matchType == MatchType.None) { + if (matchType == MatchType.NONE) { matchTypeChooser.addDefaultOption(matchType.name(), matchType); } else { matchTypeChooser.addOption(matchType.name(), matchType); @@ -156,7 +156,7 @@ public void disabledPeriodic() { private double getPreciseMatchTime() { double timerTime = preciseMatchTimer.get(); - if (DriverStation.isAutonomous()) { + if (DriverStationBackend.isAutonomous()) { return StrategyConstants.autoStart - timerTime; } else { return StrategyConstants.transitionStart - timerTime; @@ -164,7 +164,7 @@ private double getPreciseMatchTime() { } private double getMatchTime() { - double dsMatchTime = DriverStation.getMatchTime(); + double dsMatchTime = DriverStationBackend.getMatchTime(); double preciseMatchTime = getPreciseMatchTime(); if (Math.abs(dsMatchTime - preciseMatchTime) @@ -181,7 +181,7 @@ public void enabledPeriodic(boolean weWonAutoOverridePressed, boolean weLostAuto DriverStationSim.setMatchType(matchTypeChooser.get()); } - if (DriverStation.isTeleop()) { + if (DriverStationBackend.isTeleop()) { hasTeleopEnabled = true; } @@ -227,21 +227,18 @@ public void enabledPeriodic(boolean weWonAutoOverridePressed, boolean weLostAuto } private void checkGameDataForAutoWinner() { - String gameData = DriverStation.getGameSpecificMessage(); - - if (gameData == null) { - return; - } + DriverStationBackend.getGameData().ifPresent((gameData) -> { if (gameData.length() > 0) { if (gameData.startsWith("R")) { - wonAuto = Optional.of(Alliance.Red); + wonAuto = Optional.of(Alliance.RED); receivedAutoWinnerFromFMS = true; } else if (gameData.startsWith("B")) { - wonAuto = Optional.of(Alliance.Blue); + wonAuto = Optional.of(Alliance.BLUE); receivedAutoWinnerFromFMS = true; } } + }); } public Optional getAutoWinner() { @@ -251,9 +248,9 @@ public Optional getAutoWinner() { public MatchShift getCurrentShift(double currentMatchTime) { // The behavior of this method is determined largely by the docs here - // https://github.wpilib.org/allwpilib/docs/release/java/edu/wpi/first/wpilibj/DriverStation.html#getMatchTime() + // https://github.wpilib.org/allwpilib/docs/release/java/org.wpilib.driverstation.DriverStation.html#getMatchTime() if (isInMatch()) { - if (DriverStation.isAutonomous()) { + if (DriverStationBackend.isAutonomous()) { return MatchShift.Auto; } else { return getTeleopShiftFromMatchTime(currentMatchTime); diff --git a/src/main/java/frc/robot/generated/TunerConstants.java b/src/main/java/frc/robot/generated/TunerConstants.java index 326ee90b..651984b8 100644 --- a/src/main/java/frc/robot/generated/TunerConstants.java +++ b/src/main/java/frc/robot/generated/TunerConstants.java @@ -1,6 +1,6 @@ package frc.robot.generated; -import static edu.wpi.first.units.Units.*; +import static org.wpilib.units.Units.*; import com.ctre.phoenix6.CANBus; import com.ctre.phoenix6.configs.*; @@ -8,10 +8,10 @@ import com.ctre.phoenix6.signals.*; import com.ctre.phoenix6.swerve.*; import com.ctre.phoenix6.swerve.SwerveModuleConstants.*; -import edu.wpi.first.math.Matrix; -import edu.wpi.first.math.numbers.N1; -import edu.wpi.first.math.numbers.N3; -import edu.wpi.first.units.measure.*; +import org.wpilib.math.linalg.Matrix; +import org.wpilib.math.numbers.N1; +import org.wpilib.math.numbers.N3; +import org.wpilib.units.measure.*; // 2025 B BOT CONSTANTS!!!!! (dont remove put somewhere else please) diff --git a/src/main/java/frc/robot/subsystems/climber/ClimberState.java b/src/main/java/frc/robot/subsystems/climber/ClimberState.java index d92f3eb2..51b68852 100644 --- a/src/main/java/frc/robot/subsystems/climber/ClimberState.java +++ b/src/main/java/frc/robot/subsystems/climber/ClimberState.java @@ -1,10 +1,10 @@ package frc.robot.subsystems.climber; -import static edu.wpi.first.units.Units.RadiansPerSecond; +import static org.wpilib.units.Units.RadiansPerSecond; import coppercore.controls.state_machine.State; import coppercore.controls.state_machine.StateMachine; -import edu.wpi.first.units.AngularVelocityUnit; +import org.wpilib.units.AngularVelocityUnit; import frc.robot.constants.JsonConstants; // Copilot autocomplete was used to help write this file diff --git a/src/main/java/frc/robot/subsystems/climber/ClimberSubsystem.java b/src/main/java/frc/robot/subsystems/climber/ClimberSubsystem.java index 4cc7f131..51a46d2a 100644 --- a/src/main/java/frc/robot/subsystems/climber/ClimberSubsystem.java +++ b/src/main/java/frc/robot/subsystems/climber/ClimberSubsystem.java @@ -1,14 +1,14 @@ package frc.robot.subsystems.climber; -import static edu.wpi.first.units.Units.Amps; -import static edu.wpi.first.units.Units.Degrees; -import static edu.wpi.first.units.Units.Meters; -import static edu.wpi.first.units.Units.Radians; -import static edu.wpi.first.units.Units.RadiansPerSecond; -import static edu.wpi.first.units.Units.RotationsPerSecond; -import static edu.wpi.first.units.Units.RotationsPerSecondPerSecond; -import static edu.wpi.first.units.Units.Seconds; -import static edu.wpi.first.units.Units.Volts; +import static org.wpilib.units.Units.Amps; +import static org.wpilib.units.Units.Degrees; +import static org.wpilib.units.Units.Meters; +import static org.wpilib.units.Units.Radians; +import static org.wpilib.units.Units.RadiansPerSecond; +import static org.wpilib.units.Units.RotationsPerSecond; +import static org.wpilib.units.Units.RotationsPerSecondPerSecond; +import static org.wpilib.units.Units.Seconds; +import static org.wpilib.units.Units.Volts; import coppercore.controls.state_machine.StateMachine; import coppercore.math.Lazy; @@ -20,14 +20,13 @@ import coppercore.wpilib_interface.subsystems.motors.MotorInputsAutoLogged; import coppercore.wpilib_interface.subsystems.motors.profile.MotionProfileConfig; import coppercore.wpilib_interface.tuning.TestModeManager; -import edu.wpi.first.units.VoltageUnit; -import edu.wpi.first.units.measure.Angle; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.units.measure.Distance; -import edu.wpi.first.units.measure.MutVoltage; -import edu.wpi.first.units.measure.Voltage; -import edu.wpi.first.wpilibj.DriverStation; -import edu.wpi.first.wpilibj.RobotController; +import org.wpilib.units.VoltageUnit; +import org.wpilib.units.measure.Angle; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.units.measure.Distance; +import org.wpilib.units.measure.Voltage; +import org.wpilib.driverstation.internal.DriverStationBackend; +import org.wpilib.system.RobotController; import frc.robot.constants.JsonConstants; import frc.robot.subsystems.climber.ClimberState.HomingWaitForMovementState; import frc.robot.subsystems.climber.ClimberState.HomingWaitForStoppingState; @@ -83,10 +82,10 @@ private enum ClimberAction { Lazy climberTuningAmps; Lazy climberTuningVolts; - LoggedTunableMeasure hangVoltage = + LoggedTunableMeasure hangVoltage = new LoggedTunableMeasure<>( "ClimberTunables/hangVoltage", - JsonConstants.climberConstants.hangClimbVoltage.mutableCopy(), + JsonConstants.climberConstants.hangClimbVoltage, Volts, true); @@ -108,7 +107,7 @@ public ClimberSubsystem(MotorIO motor) { waitForHomingState .when( - climber -> DriverStation.isEnabled() && climber.isClimberTestMode(), + climber -> DriverStationBackend.isEnabled() && climber.isClimberTestMode(), "In climber test mode (must home first)") .transitionTo(homingWaitForMovementState); waitForHomingState.whenFinished("Should home").transitionTo(homingWaitForMovementState); @@ -208,7 +207,7 @@ public ClimberSubsystem(MotorIO motor) { @Override public void monitoredPeriodic() { - long startTimeUs = RobotController.getFPGATime(); + long startTimeUs = RobotController.getTime(); motor.updateInputs(inputs); Logger.processInputs("Climber/inputs", inputs); @@ -218,7 +217,7 @@ public void monitoredPeriodic() { Logger.recordOutput("Climber/State", stateMachine.getCurrentState().getName()); stateMachine.periodic(); - long endTimeUs = RobotController.getFPGATime(); + long endTimeUs = RobotController.getTime(); if (JsonConstants.featureFlags.logPeriodicTiming) { Logger.recordOutput("PeriodicTime/climberMs", (endTimeUs - startTimeUs) / 1000.0); } diff --git a/src/main/java/frc/robot/subsystems/drive/Drive.java b/src/main/java/frc/robot/subsystems/drive/Drive.java index cfe7ccce..643b83e7 100644 --- a/src/main/java/frc/robot/subsystems/drive/Drive.java +++ b/src/main/java/frc/robot/subsystems/drive/Drive.java @@ -7,7 +7,7 @@ package frc.robot.subsystems.drive; -import static edu.wpi.first.units.Units.*; +import static org.wpilib.units.Units.*; import com.pathplanner.lib.util.PathPlannerLogging; import coppercore.controls.ServiceThread; @@ -15,35 +15,33 @@ import coppercore.wpilib_interface.DriveTemplate; import coppercore.wpilib_interface.alliance_util.AllianceUtil; import coppercore.wpilib_interface.tuning.PIDGains; -import edu.wpi.first.hal.FRCNetComm.tInstances; -import edu.wpi.first.hal.FRCNetComm.tResourceType; -import edu.wpi.first.hal.HAL; -import edu.wpi.first.math.Matrix; -import edu.wpi.first.math.VecBuilder; -import edu.wpi.first.math.estimator.SwerveDrivePoseEstimator; -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.math.geometry.Twist2d; -import edu.wpi.first.math.kinematics.ChassisSpeeds; -import edu.wpi.first.math.kinematics.SwerveDriveKinematics; -import edu.wpi.first.math.kinematics.SwerveModulePosition; -import edu.wpi.first.math.kinematics.SwerveModuleState; -import edu.wpi.first.math.numbers.N1; -import edu.wpi.first.math.numbers.N3; -import edu.wpi.first.units.measure.Current; -import edu.wpi.first.wpilibj.Alert; -import edu.wpi.first.wpilibj.Alert.AlertType; -import edu.wpi.first.wpilibj.DriverStation; -import edu.wpi.first.wpilibj.DriverStation.Alliance; -import edu.wpi.first.wpilibj.RobotController; -import edu.wpi.first.wpilibj.Timer; -import edu.wpi.first.wpilibj.smartdashboard.Field2d; -import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; -import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.InstantCommand; -import edu.wpi.first.wpilibj2.command.SubsystemBase; -import edu.wpi.first.wpilibj2.command.sysid.SysIdRoutine; +import org.wpilib.hardware.hal.HAL; +import org.wpilib.math.linalg.Matrix; +import org.wpilib.math.linalg.VecBuilder; +import org.wpilib.math.estimator.SwerveDrivePoseEstimator; +import org.wpilib.math.geometry.Pose2d; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.math.geometry.Translation2d; +import org.wpilib.math.geometry.Twist2d; +import org.wpilib.math.kinematics.ChassisVelocities; +import org.wpilib.math.kinematics.SwerveDriveKinematics; +import org.wpilib.math.kinematics.SwerveModulePosition; +import org.wpilib.math.kinematics.SwerveModuleVelocity; +import org.wpilib.math.numbers.N1; +import org.wpilib.math.numbers.N3; +import org.wpilib.units.measure.Current; +import org.wpilib.driverstation.Alert; +import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.Alliance; +import org.wpilib.driverstation.internal.DriverStationBackend; +import org.wpilib.system.RobotController; +import org.wpilib.system.Timer; +import org.wpilib.smartdashboard.Field2d; +import org.wpilib.smartdashboard.SmartDashboard; +import org.wpilib.command2.Command; +import org.wpilib.command2.InstantCommand; +import org.wpilib.command2.SubsystemBase; +import org.wpilib.command2.sysid.SysIdRoutine; import frc.robot.Constants; import frc.robot.Constants.Mode; import frc.robot.constants.JsonConstants; @@ -83,7 +81,7 @@ public class Drive extends SubsystemBase implements DriveTemplate { private final Module[] modules = new Module[4]; // FL, FR, BL, BR private final SysIdRoutine sysId; private final Alert gyroDisconnectedAlert = - new Alert("Disconnected gyro, using kinematics as fallback.", AlertType.kError); + new Alert("Disconnected gyro, using kinematics as fallback.", Alert.Level.HIGH); private SwerveDriveKinematics kinematics = new SwerveDriveKinematics(getModuleTranslations()); private Rotation2d rawGyroRotation = Rotation2d.kZero; @@ -138,7 +136,7 @@ public Drive( SmartDashboard.putData("ResetToAutoCurrentLimits", resetToAutoLimitsCommand); // Usage reporting for swerve template - HAL.report(tResourceType.kResourceType_RobotDrive, tInstances.kRobotDriveSwerve_AdvantageKit); + HAL.reportUsage("RobotDrive", "Swerve_AdvantageKit"); // Start odometry thread PhoenixOdometryThread.getInstance().start(); @@ -184,7 +182,7 @@ public Drive( @Override public void periodic() { - long startTimeUs = RobotController.getFPGATime(); + long startTimeUs = RobotController.getTime(); odometryLock.lock(); // Prevents odometry updates while reading data gyroIO.updateInputs(gyroInputs); Logger.processInputs("Drive/Gyro", gyroInputs); @@ -198,16 +196,16 @@ public void periodic() { TotalCurrentCalculator.recordCurrent(hashCode(), supplyCurrentSum); // Stop moving when disabled - if (DriverStation.isDisabled()) { + if (DriverStationBackend.isDisabled()) { for (var module : modules) { module.stop(); } } // Log empty setpoint states when disabled - if (DriverStation.isDisabled()) { - Logger.recordOutput("SwerveStates/Setpoints", new SwerveModuleState[] {}); - Logger.recordOutput("SwerveStates/SetpointsOptimized", new SwerveModuleState[] {}); + if (DriverStationBackend.isDisabled()) { + Logger.recordOutput("SwerveStates/Setpoints", new SwerveModuleVelocity[] {}); + Logger.recordOutput("SwerveStates/SetpointsOptimized", new SwerveModuleVelocity[] {}); } // Update odometry @@ -224,8 +222,8 @@ public void periodic() { modulePositions[moduleIndex] = modules[moduleIndex].getOdometryPositions()[i]; moduleDeltas[moduleIndex] = new SwerveModulePosition( - modulePositions[moduleIndex].distanceMeters - - lastModulePositions[moduleIndex].distanceMeters, + modulePositions[moduleIndex].distance + - lastModulePositions[moduleIndex].distance, modulePositions[moduleIndex].angle); lastModulePositions[moduleIndex] = modulePositions[moduleIndex]; } @@ -256,7 +254,8 @@ public void periodic() { } twist = new Twist2d(twist.dx, twist.dy, deltaYaw.getRadians()); - totalDeltaPose = totalDeltaPose.exp(twist); + totalDeltaPose = totalDeltaPose.plus(twist.exp()); + } else { poseEstimator.updateWithTime(sampleTimestamps[i], rawGyroRotation, modulePositions); } @@ -264,7 +263,7 @@ public void periodic() { // Apply update if (JsonConstants.featureFlags.useMAPoseEstimator) { - Twist2d totalTwist = Pose2d.kZero.log(totalDeltaPose); + Twist2d totalTwist = totalDeltaPose.minus(Pose2d.kZero).log(); lastGyroYaw = gyroInputs.connected ? gyroInputs.yawPosition : rawGyroRotation; maPoseEstimator.addDriveData(Timer.getTimestamp(), totalTwist); } @@ -274,7 +273,7 @@ public void periodic() { field2d.setRobotPose(getPose()); - long endTimeUs = RobotController.getFPGATime(); + long endTimeUs = RobotController.getTime(); if (JsonConstants.featureFlags.logPeriodicTiming) { Logger.recordOutput("PeriodicTime/driveMs", (endTimeUs - startTimeUs) / 1000.0); } @@ -285,11 +284,11 @@ public void periodic() { * * @param speeds Speeds in meters/sec */ - public void runVelocity(ChassisSpeeds speeds) { + public void runVelocity(ChassisVelocities speeds) { // Calculate module setpoints - ChassisSpeeds discreteSpeeds = ChassisSpeeds.discretize(speeds, 0.02); - SwerveModuleState[] setpointStates = kinematics.toSwerveModuleStates(discreteSpeeds); - SwerveDriveKinematics.desaturateWheelSpeeds( + ChassisVelocities discreteSpeeds = speeds.discretize(0.02); + SwerveModuleVelocity[] setpointStates = kinematics.toSwerveModuleVelocities(discreteSpeeds); + setpointStates = SwerveDriveKinematics.desaturateWheelVelocities( setpointStates, JsonConstants.physicalDriveConstants.kSpeedAt12Volts); // Log unoptimized setpoints and setpoint speeds @@ -305,26 +304,26 @@ public void runVelocity(ChassisSpeeds speeds) { Logger.recordOutput("SwerveStates/SetpointsOptimized", setpointStates); } - public void setGoalSpeedsBlueOrigins(ChassisSpeeds goalSpeeds) { + public void setGoalSpeedsBlueOrigins(ChassisVelocities goalSpeeds) { Rotation2d robotRotation = getRotation(); - runVelocity(ChassisSpeeds.fromFieldRelativeSpeeds(goalSpeeds, robotRotation)); + runVelocity(goalSpeeds.toRobotRelative(robotRotation)); } @Override - public void setGoalSpeeds(ChassisSpeeds goalSpeeds, boolean isFieldCentric) { + public void setGoalVelocities(ChassisVelocities goalSpeeds, boolean isFieldCentric) { Logger.recordOutput("drive/goalSpeeds", goalSpeeds); - ChassisSpeeds speeds = getChassisSpeeds(); + ChassisVelocities speeds = getChassisVelocities(); if ((xLockPressed || inDefenseMode) - && Math.abs(goalSpeeds.vxMetersPerSecond) <= 1e-3 - && Math.abs(goalSpeeds.vyMetersPerSecond) <= 1e-3 - && Math.abs(goalSpeeds.omegaRadiansPerSecond) <= 1e-3 + && Math.abs(goalSpeeds.vx) <= 1e-3 + && Math.abs(goalSpeeds.vy) <= 1e-3 + && Math.abs(goalSpeeds.omega) <= 1e-3 && Math.sqrt( - speeds.vxMetersPerSecond * speeds.vxMetersPerSecond - + speeds.vyMetersPerSecond * speeds.vyMetersPerSecond) + speeds.vx * speeds.vx + + speeds.vy * speeds.vy) <= JsonConstants.driveConstants.xLockMaxVelocityMetersPerSecond - && Math.abs(speeds.omegaRadiansPerSecond) + && Math.abs(speeds.omega) <= JsonConstants.driveConstants.xLockMaxVelocityRadiansPerSecond) { stopWithX(); return; @@ -333,15 +332,15 @@ public void setGoalSpeeds(ChassisSpeeds goalSpeeds, boolean isFieldCentric) { if (isFieldCentric) { // Adjust for field-centric control boolean isFlipped = - DriverStation.getAlliance().isPresent() - && DriverStation.getAlliance().get() == Alliance.Red; + DriverStationBackend.getAlliance().isPresent() + && DriverStationBackend.getAlliance().get() == Alliance.RED; Rotation2d robotRotation = isFlipped ? getRotation().plus(new Rotation2d(Math.PI)) // Flip orientation for Red Alliance : getRotation(); - runVelocity(ChassisSpeeds.fromFieldRelativeSpeeds(goalSpeeds, robotRotation)); + runVelocity(goalSpeeds.toRobotRelative(robotRotation)); } else { Logger.recordOutput("Drive/DesiredRobotCentricSpeeds", goalSpeeds); @@ -358,7 +357,7 @@ public void runCharacterization(double output) { /** Stops the drive. */ public void stop() { - runVelocity(new ChassisSpeeds()); + runVelocity(new ChassisVelocities()); } /** @@ -388,8 +387,8 @@ public Command sysIdDynamic(SysIdRoutine.Direction direction) { /** Returns the module states (turn angles and drive velocities) for all of the modules. */ @AutoLogOutput(key = "SwerveStates/Measured") - private SwerveModuleState[] getModuleStates() { - SwerveModuleState[] states = new SwerveModuleState[4]; + private SwerveModuleVelocity[] getModuleStates() { + SwerveModuleVelocity[] states = new SwerveModuleVelocity[4]; for (int i = 0; i < 4; i++) { states[i] = modules[i].getState(); } @@ -406,9 +405,9 @@ private SwerveModulePosition[] getModulePositions() { } /** Returns the measured chassis speeds of the robot. */ - @AutoLogOutput(key = "SwerveChassisSpeeds/Measured") - public ChassisSpeeds getChassisSpeeds() { - return kinematics.toChassisSpeeds(getModuleStates()); + @AutoLogOutput(key = "SwerveChassisVelocities/Measured") + public ChassisVelocities getChassisVelocities() { + return kinematics.toChassisVelocities(getModuleStates()); } /** Returns the position of each module in radians. */ @@ -531,9 +530,9 @@ public void seedHeadingForward() { Rotation2d heading = switch (AllianceUtil.getAlliance()) { // Red alliance is "flipped" (forward is -x) - case Red -> Rotation2d.k180deg; + case RED -> Rotation2d.k180deg; // Blue alliance is +x forward - case Blue -> Rotation2d.kZero; + case BLUE -> Rotation2d.kZero; }; setPose(new Pose2d(currentPose.getX(), currentPose.getY(), heading)); diff --git a/src/main/java/frc/robot/subsystems/drive/DriveCoordinator.java b/src/main/java/frc/robot/subsystems/drive/DriveCoordinator.java index dbd68865..33628152 100644 --- a/src/main/java/frc/robot/subsystems/drive/DriveCoordinator.java +++ b/src/main/java/frc/robot/subsystems/drive/DriveCoordinator.java @@ -3,11 +3,11 @@ import coppercore.wpilib_interface.DriveWithJoysticks; import coppercore.wpilib_interface.tuning.LoggedTunablePIDGains; import coppercore.wpilib_interface.tuning.TestModeManager; -import edu.wpi.first.math.geometry.Pose2d; -import edu.wpi.first.wpilibj.RobotController; -import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.InstantCommand; -import edu.wpi.first.wpilibj2.command.SubsystemBase; +import org.wpilib.math.geometry.Pose2d; +import org.wpilib.system.RobotController; +import org.wpilib.command2.Command; +import org.wpilib.command2.InstantCommand; +import org.wpilib.command2.SubsystemBase; import frc.robot.constants.JsonConstants; import org.littletonrobotics.junction.Logger; @@ -174,7 +174,7 @@ public void autoPilotToPose(Pose2d pose) { @Override public void periodic() { - long startTimeUs = RobotController.getFPGATime(); + long startTimeUs = RobotController.getTime(); if (testModeManager.isInTestMode()) { testPeriodic(); @@ -196,7 +196,7 @@ public void periodic() { "DriveCoordinator/CurrentCommand", activeCommand == null ? "None" : activeCommand.getName()); - long endTimeUs = RobotController.getFPGATime(); + long endTimeUs = RobotController.getTime(); if (JsonConstants.featureFlags.logPeriodicTiming) { Logger.recordOutput("PeriodicTime/driveCoordinatorMs", (endTimeUs - startTimeUs) / 1000.0); } diff --git a/src/main/java/frc/robot/subsystems/drive/DriveCoordinatorCommands.java b/src/main/java/frc/robot/subsystems/drive/DriveCoordinatorCommands.java index 6ec57ed5..9550171f 100644 --- a/src/main/java/frc/robot/subsystems/drive/DriveCoordinatorCommands.java +++ b/src/main/java/frc/robot/subsystems/drive/DriveCoordinatorCommands.java @@ -1,16 +1,16 @@ package frc.robot.subsystems.drive; -import static edu.wpi.first.units.Units.MetersPerSecond; +import static org.wpilib.units.Units.MetersPerSecond; import com.therekrab.autopilot.APConstraints; import com.therekrab.autopilot.APProfile; import com.therekrab.autopilot.APTarget; import com.therekrab.autopilot.Autopilot; import com.therekrab.autopilot.Autopilot.APResult; -import edu.wpi.first.math.controller.PIDController; -import edu.wpi.first.math.geometry.Pose2d; -import edu.wpi.first.math.kinematics.ChassisSpeeds; -import edu.wpi.first.wpilibj2.command.Command; +import org.wpilib.math.controller.PIDController; +import org.wpilib.math.geometry.Pose2d; +import org.wpilib.math.kinematics.ChassisVelocities; +import org.wpilib.command2.Command; import frc.robot.constants.JsonConstants; import java.security.InvalidParameterException; import org.littletonrobotics.junction.Logger; @@ -66,7 +66,7 @@ public void initialize() { @Override public void execute() { - var chassisSpeeds = driveCoordinator.drive.getChassisSpeeds(); + var chassisSpeeds = driveCoordinator.drive.getChassisVelocities(); var currentPose = driveCoordinator.drive.getPose(); APResult output = autoPilot.calculate(currentPose, chassisSpeeds, target); @@ -79,7 +79,7 @@ public void execute() { headingController.calculate(currentHeading.getRadians(), desiredHeading.getRadians()); var speeds = - new ChassisSpeeds( + new ChassisVelocities( output.vx().in(MetersPerSecond), output.vy().in(MetersPerSecond), omega); driveCoordinator.drive.setGoalSpeedsBlueOrigins(speeds); diff --git a/src/main/java/frc/robot/subsystems/drive/GyroIO.java b/src/main/java/frc/robot/subsystems/drive/GyroIO.java index 4e9754f9..be3b1ccb 100644 --- a/src/main/java/frc/robot/subsystems/drive/GyroIO.java +++ b/src/main/java/frc/robot/subsystems/drive/GyroIO.java @@ -7,7 +7,7 @@ package frc.robot.subsystems.drive; -import edu.wpi.first.math.geometry.Rotation2d; +import org.wpilib.math.geometry.Rotation2d; import org.littletonrobotics.junction.AutoLog; public interface GyroIO { diff --git a/src/main/java/frc/robot/subsystems/drive/GyroIONavX.java b/src/main/java/frc/robot/subsystems/drive/GyroIONavX.java index 45e6f44a..6504b457 100644 --- a/src/main/java/frc/robot/subsystems/drive/GyroIONavX.java +++ b/src/main/java/frc/robot/subsystems/drive/GyroIONavX.java @@ -15,8 +15,8 @@ // import com.studica.frc.AHRS; // import com.studica.frc.AHRS.NavXComType; -// import edu.wpi.first.math.geometry.Rotation2d; -// import edu.wpi.first.math.util.Units; +// import org.wpilib.math.geometry.Rotation2d; +// import org.wpilib.math.util.Units; // import java.util.Queue; /** IO implementation for NavX. */ diff --git a/src/main/java/frc/robot/subsystems/drive/GyroIOPigeon2.java b/src/main/java/frc/robot/subsystems/drive/GyroIOPigeon2.java index 8a20b908..5bc875c0 100644 --- a/src/main/java/frc/robot/subsystems/drive/GyroIOPigeon2.java +++ b/src/main/java/frc/robot/subsystems/drive/GyroIOPigeon2.java @@ -12,10 +12,10 @@ import com.ctre.phoenix6.configs.Pigeon2Configuration; import com.ctre.phoenix6.hardware.Pigeon2; import coppercore.wpilib_interface.subsystems.StatusSignalRefresher; -import edu.wpi.first.math.geometry.Rotation2d; -import edu.wpi.first.math.util.Units; -import edu.wpi.first.units.measure.Angle; -import edu.wpi.first.units.measure.AngularVelocity; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.math.util.Units; +import org.wpilib.units.measure.Angle; +import org.wpilib.units.measure.AngularVelocity; import frc.robot.constants.JsonConstants; import java.util.Queue; diff --git a/src/main/java/frc/robot/subsystems/drive/Module.java b/src/main/java/frc/robot/subsystems/drive/Module.java index 83c03a3d..c429a8e0 100644 --- a/src/main/java/frc/robot/subsystems/drive/Module.java +++ b/src/main/java/frc/robot/subsystems/drive/Module.java @@ -11,14 +11,14 @@ import com.ctre.phoenix6.configs.TalonFXConfiguration; import com.ctre.phoenix6.swerve.SwerveModuleConstants; import coppercore.wpilib_interface.tuning.PIDGains; -import edu.wpi.first.math.geometry.Rotation2d; -import edu.wpi.first.math.kinematics.SwerveModulePosition; -import edu.wpi.first.math.kinematics.SwerveModuleState; -import edu.wpi.first.math.util.Units; -import edu.wpi.first.units.measure.Current; -import edu.wpi.first.wpilibj.Alert; -import edu.wpi.first.wpilibj.Alert.AlertType; -import edu.wpi.first.wpilibj.RobotController; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.math.kinematics.SwerveModulePosition; +import org.wpilib.math.kinematics.SwerveModuleVelocity; +import org.wpilib.math.util.Units; +import org.wpilib.units.measure.Current; +import org.wpilib.annotation.NoDiscard; +import org.wpilib.driverstation.Alert; +import org.wpilib.system.RobotController; import frc.robot.Constants; import frc.robot.Constants.Mode; import org.littletonrobotics.junction.Logger; @@ -49,14 +49,14 @@ public Module( driveDisconnectedAlert = new Alert( "Disconnected drive motor on module " + Integer.toString(index) + ".", - AlertType.kError); + Alert.Level.HIGH); turnDisconnectedAlert = new Alert( - "Disconnected turn motor on module " + Integer.toString(index) + ".", AlertType.kError); + "Disconnected turn motor on module " + Integer.toString(index) + ".", Alert.Level.HIGH); turnEncoderDisconnectedAlert = new Alert( "Disconnected turn encoder on module " + Integer.toString(index) + ".", - AlertType.kError); + Alert.Level.HIGH); loggerKey = "Drive/Module" + Integer.toString(index); } @@ -99,13 +99,13 @@ public double getSupplyCurrentAmps() { } /** Runs the module with the specified setpoint state. Mutates the state to optimize it. */ - public void runSetpoint(SwerveModuleState state) { + public void runSetpoint(SwerveModuleVelocity state) { // Optimize velocity setpoint - state.optimize(getAngle()); - state.cosineScale(inputs.turnPosition); + state = state.optimize(getAngle()); + state = state.cosineScale(inputs.turnPosition); // Apply setpoints - io.setDriveVelocity(state.speedMetersPerSecond / constants.WheelRadius); + io.setDriveVelocity(state.velocity / constants.WheelRadius); io.setTurnPosition(state.angle); } @@ -142,8 +142,8 @@ public SwerveModulePosition getPosition() { } /** Returns the module state (turn angle and drive velocity). */ - public SwerveModuleState getState() { - return new SwerveModuleState(getVelocityMetersPerSec(), getAngle()); + public SwerveModuleVelocity getState() { + return new SwerveModuleVelocity(getVelocityMetersPerSec(), getAngle()); } /** Returns the module positions received this cycle. */ diff --git a/src/main/java/frc/robot/subsystems/drive/ModuleIO.java b/src/main/java/frc/robot/subsystems/drive/ModuleIO.java index 962761c2..4eb70685 100644 --- a/src/main/java/frc/robot/subsystems/drive/ModuleIO.java +++ b/src/main/java/frc/robot/subsystems/drive/ModuleIO.java @@ -8,8 +8,8 @@ package frc.robot.subsystems.drive; import coppercore.wpilib_interface.tuning.PIDGains; -import edu.wpi.first.math.geometry.Rotation2d; -import edu.wpi.first.units.measure.Current; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.units.measure.Current; import org.littletonrobotics.junction.AutoLog; public interface ModuleIO { diff --git a/src/main/java/frc/robot/subsystems/drive/ModuleIOSim.java b/src/main/java/frc/robot/subsystems/drive/ModuleIOSim.java index c9870d68..3725c426 100644 --- a/src/main/java/frc/robot/subsystems/drive/ModuleIOSim.java +++ b/src/main/java/frc/robot/subsystems/drive/ModuleIOSim.java @@ -11,14 +11,13 @@ import com.ctre.phoenix6.configs.TalonFXConfiguration; import com.ctre.phoenix6.swerve.SwerveModuleConstants; import coppercore.wpilib_interface.tuning.PIDGains; -import edu.wpi.first.math.MathUtil; -import edu.wpi.first.math.controller.PIDController; -import edu.wpi.first.math.geometry.Rotation2d; -import edu.wpi.first.math.system.plant.DCMotor; -import edu.wpi.first.math.system.plant.LinearSystemId; -import edu.wpi.first.math.util.Units; -import edu.wpi.first.wpilibj.Timer; -import edu.wpi.first.wpilibj.simulation.DCMotorSim; +import org.wpilib.math.controller.PIDController; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.math.system.DCMotor; +import org.wpilib.math.system.Models; +import org.wpilib.math.util.Units; +import org.wpilib.system.Timer; +import org.wpilib.simulation.DCMotorSim; /** * Physics sim implementation of module IO. The sim models are configured using a set of module @@ -55,12 +54,12 @@ public ModuleIOSim( // Create drive and turn sim models driveSim = new DCMotorSim( - LinearSystemId.createDCMotorSystem( + Models.singleJointedArmFromPhysicalConstants( DRIVE_GEARBOX, constants.DriveInertia, constants.DriveMotorGearRatio), DRIVE_GEARBOX); turnSim = new DCMotorSim( - LinearSystemId.createDCMotorSystem( + Models.singleJointedArmFromPhysicalConstants( TURN_GEARBOX, constants.SteerInertia, constants.SteerMotorGearRatio), TURN_GEARBOX); @@ -73,41 +72,41 @@ public void updateInputs(ModuleIOInputs inputs) { // Run closed-loop control if (driveClosedLoop) { driveAppliedVolts = - driveFFVolts + driveController.calculate(driveSim.getAngularVelocityRadPerSec()); + driveFFVolts + driveController.calculate(driveSim.getAngularVelocity()); } else { driveController.reset(); } if (turnClosedLoop) { - turnAppliedVolts = turnController.calculate(turnSim.getAngularPositionRad()); + turnAppliedVolts = turnController.calculate(turnSim.getAngularPosition()); } else { turnController.reset(); } // Update simulation state - driveSim.setInputVoltage(MathUtil.clamp(driveAppliedVolts, -12.0, 12.0)); - turnSim.setInputVoltage(MathUtil.clamp(turnAppliedVolts, -12.0, 12.0)); + driveSim.setInputVoltage(Math.clamp(driveAppliedVolts, -12.0, 12.0)); + turnSim.setInputVoltage(Math.clamp(turnAppliedVolts, -12.0, 12.0)); driveSim.update(0.02); turnSim.update(0.02); // Update drive inputs inputs.driveConnected = true; - inputs.drivePositionRad = driveSim.getAngularPositionRad(); - inputs.driveVelocityRadPerSec = driveSim.getAngularVelocityRadPerSec(); + inputs.drivePositionRad = driveSim.getAngularPosition(); + inputs.driveVelocityRadPerSec = driveSim.getAngularVelocity(); inputs.driveAppliedVolts = driveAppliedVolts; - inputs.driveCurrentAmps = Math.abs(driveSim.getCurrentDrawAmps()); + inputs.driveCurrentAmps = Math.abs(driveSim.getCurrentDraw()); // Update turn inputs inputs.turnConnected = true; inputs.turnEncoderConnected = true; - inputs.turnAbsolutePosition = new Rotation2d(turnSim.getAngularPositionRad()); - inputs.turnPosition = new Rotation2d(turnSim.getAngularPositionRad()); - inputs.turnVelocityRadPerSec = turnSim.getAngularVelocityRadPerSec(); + inputs.turnAbsolutePosition = new Rotation2d(turnSim.getAngularPosition()); + inputs.turnPosition = new Rotation2d(turnSim.getAngularPosition()); + inputs.turnVelocityRadPerSec = turnSim.getAngularVelocity(); inputs.turnAppliedVolts = turnAppliedVolts; - inputs.turnCurrentAmps = Math.abs(turnSim.getCurrentDrawAmps()); + inputs.turnCurrentAmps = Math.abs(turnSim.getCurrentDraw()); // Update odometry inputs (50Hz because high-frequency odometry in sim doesn't // matter) - inputs.odometryTimestamps = new double[] {Timer.getFPGATimestamp()}; + inputs.odometryTimestamps = new double[] {Timer.getTimestamp()}; inputs.odometryDrivePositionsRad = new double[] {inputs.drivePositionRad}; inputs.odometryTurnPositions = new Rotation2d[] {inputs.turnPosition}; } diff --git a/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFX.java b/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFX.java index d412eefa..65723c9f 100644 --- a/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFX.java +++ b/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFX.java @@ -31,13 +31,13 @@ import coppercore.wpilib_interface.subsystems.StatusSignalRefresher; import coppercore.wpilib_interface.subsystems.configs.CANDeviceID; import coppercore.wpilib_interface.tuning.PIDGains; -import edu.wpi.first.math.filter.Debouncer; -import edu.wpi.first.math.geometry.Rotation2d; -import edu.wpi.first.math.util.Units; -import edu.wpi.first.units.measure.Angle; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.units.measure.Current; -import edu.wpi.first.units.measure.Voltage; +import org.wpilib.math.filter.Debouncer; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.math.util.Units; +import org.wpilib.units.measure.Angle; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.units.measure.Current; +import org.wpilib.units.measure.Voltage; import frc.robot.constants.JsonConstants; import java.util.Queue; diff --git a/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFXS.java b/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFXS.java index 46a56565..bddb582a 100644 --- a/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFXS.java +++ b/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFXS.java @@ -26,13 +26,13 @@ import com.ctre.phoenix6.signals.NeutralModeValue; import com.ctre.phoenix6.swerve.SwerveModuleConstants; import coppercore.wpilib_interface.tuning.PIDGains; -import edu.wpi.first.math.filter.Debouncer; -import edu.wpi.first.math.geometry.Rotation2d; -import edu.wpi.first.math.util.Units; -import edu.wpi.first.units.measure.Angle; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.units.measure.Current; -import edu.wpi.first.units.measure.Voltage; +import org.wpilib.math.filter.Debouncer; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.math.util.Units; +import org.wpilib.units.measure.Angle; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.units.measure.Current; +import org.wpilib.units.measure.Voltage; import frc.robot.constants.JsonConstants; import java.util.Queue; diff --git a/src/main/java/frc/robot/subsystems/drive/PhoenixOdometryThread.java b/src/main/java/frc/robot/subsystems/drive/PhoenixOdometryThread.java index 60390e4f..8e4335ca 100644 --- a/src/main/java/frc/robot/subsystems/drive/PhoenixOdometryThread.java +++ b/src/main/java/frc/robot/subsystems/drive/PhoenixOdometryThread.java @@ -9,8 +9,8 @@ import com.ctre.phoenix6.BaseStatusSignal; import com.ctre.phoenix6.StatusSignal; -import edu.wpi.first.units.measure.Angle; -import edu.wpi.first.wpilibj.RobotController; +import org.wpilib.units.measure.Angle; +import org.wpilib.system.RobotController; import frc.robot.constants.JsonConstants; import java.util.ArrayList; import java.util.List; @@ -131,7 +131,7 @@ public void run() { // Sample timestamp is current FPGA time minus average CAN latency // Default timestamps from Phoenix are NOT compatible with // FPGA timestamps, this solution is imperfect but close - double timestamp = RobotController.getFPGATime() / 1e6; + double timestamp = RobotController.getTime() / 1e6; double totalLatency = 0.0; for (BaseStatusSignal signal : phoenixSignals) { totalLatency += signal.getTimestamp().getLatency(); diff --git a/src/main/java/frc/robot/subsystems/hood/HoodState.java b/src/main/java/frc/robot/subsystems/hood/HoodState.java index 8fd147b8..7dcc00a8 100644 --- a/src/main/java/frc/robot/subsystems/hood/HoodState.java +++ b/src/main/java/frc/robot/subsystems/hood/HoodState.java @@ -1,10 +1,10 @@ package frc.robot.subsystems.hood; -import static edu.wpi.first.units.Units.RadiansPerSecond; +import static org.wpilib.units.Units.RadiansPerSecond; import coppercore.controls.state_machine.State; import coppercore.controls.state_machine.StateMachine; -import edu.wpi.first.units.AngularVelocityUnit; +import org.wpilib.units.AngularVelocityUnit; import frc.robot.constants.JsonConstants; /** diff --git a/src/main/java/frc/robot/subsystems/hood/HoodSubsystem.java b/src/main/java/frc/robot/subsystems/hood/HoodSubsystem.java index 2cb9b533..d5f14f9b 100644 --- a/src/main/java/frc/robot/subsystems/hood/HoodSubsystem.java +++ b/src/main/java/frc/robot/subsystems/hood/HoodSubsystem.java @@ -1,13 +1,13 @@ package frc.robot.subsystems.hood; -import static edu.wpi.first.units.Units.Amps; -import static edu.wpi.first.units.Units.Degrees; -import static edu.wpi.first.units.Units.Radians; -import static edu.wpi.first.units.Units.RadiansPerSecond; -import static edu.wpi.first.units.Units.RotationsPerSecond; -import static edu.wpi.first.units.Units.RotationsPerSecondPerSecond; -import static edu.wpi.first.units.Units.Seconds; -import static edu.wpi.first.units.Units.Volts; +import static org.wpilib.units.Units.Amps; +import static org.wpilib.units.Units.Degrees; +import static org.wpilib.units.Units.Radians; +import static org.wpilib.units.Units.RadiansPerSecond; +import static org.wpilib.units.Units.RotationsPerSecond; +import static org.wpilib.units.Units.RotationsPerSecondPerSecond; +import static org.wpilib.units.Units.Seconds; +import static org.wpilib.units.Units.Volts; import coppercore.controls.state_machine.StateMachine; import coppercore.math.Lazy; @@ -20,13 +20,12 @@ import coppercore.wpilib_interface.subsystems.motors.MotorInputsAutoLogged; import coppercore.wpilib_interface.subsystems.motors.profile.MotionProfileConfig; import coppercore.wpilib_interface.tuning.TestModeManager; -import edu.wpi.first.units.AngularVelocityUnit; -import edu.wpi.first.units.measure.Angle; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.units.measure.MutAngle; -import edu.wpi.first.wpilibj.Alert.AlertType; -import edu.wpi.first.wpilibj.DriverStation; -import edu.wpi.first.wpilibj.RobotController; +import org.wpilib.units.AngularVelocityUnit; +import org.wpilib.units.measure.Angle; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.driverstation.Alert; +import org.wpilib.driverstation.internal.DriverStationBackend; +import org.wpilib.system.RobotController; import frc.robot.CoordinationLayer.ShotMode; import frc.robot.DependencyOrderedExecutor; import frc.robot.DependencyOrderedExecutor.ActionKey; @@ -108,13 +107,12 @@ private enum HoodAction { @AutoLogOutput(key = "Hood/action") private HoodAction requestedAction = HoodAction.Idle; - private MutAngle goalExitPitch = + private Angle goalExitPitch = JsonConstants.hoodConstants .minHoodAngle - .plus(JsonConstants.hoodConstants.mechanismAngleToExitAngle) - .mutableCopy(); + .plus(JsonConstants.hoodConstants.mechanismAngleToExitAngle); - private MutAngle goalAngle = JsonConstants.hoodConstants.minHoodAngle.mutableCopy(); + private Angle goalAngle = JsonConstants.hoodConstants.minHoodAngle; // Dependencies (values from other subsystems/coordination layer passed in by the coordination // layer via setters) @@ -145,7 +143,7 @@ public HoodSubsystem(DependencyOrderedExecutor dependencyOrderedExecutor, MotorI new MonitorWithAlertBuilder() .withName("HoodMotorDisconnected") .withAlertText("Hood motor disconnected") - .withAlertType(AlertType.kError) + .withAlertType(Alert.Level.HIGH) .withTimeToFault(JsonConstants.hoodConstants.disconnectedDebounceTimeSeconds) .withLoggingEnabled(true) .withStickyness(false) @@ -168,7 +166,7 @@ public HoodSubsystem(DependencyOrderedExecutor dependencyOrderedExecutor, MotorI .when(hood -> hood.isHomingSwitchPressed(), "Homing switch is pressed") .transitionTo(idleState); homingWaitForButtonState - .when(() -> DriverStation.isEnabled(), "Robot is enabled") + .when(() -> DriverStationBackend.isEnabled(), "Robot is enabled") .transitionTo(homingWaitForMovementState); homingWaitForMovementState @@ -281,12 +279,12 @@ private void updateInputs() { @Override public void monitoredPeriodic() { - long startTimeUs = RobotController.getFPGATime(); + long startTimeUs = RobotController.getTime(); Logger.recordOutput("Hood/state", stateMachine.getCurrentState().getName()); stateMachine.periodic(); - long endTimeUs = RobotController.getFPGATime(); + long endTimeUs = RobotController.getTime(); if (JsonConstants.featureFlags.logPeriodicTiming) { Logger.recordOutput("PeriodicTime/hoodMs", (endTimeUs - startTimeUs) / 1000.0); } @@ -488,7 +486,7 @@ protected void controlToGoalAngle() { * @param goalAngle The Angle to target */ private void clampAndControlToAngle(Angle goalAngle) { - boolean shouldStowForShootingDisabled = !shootingEnabled && !DriverStation.isTest(); + boolean shouldStowForShootingDisabled = !shootingEnabled && !DriverStationBackend.isUtility(); boolean shouldStow = shouldStowForShootingDisabled || shouldStowForTrench || shouldStowForIntakeOrDefense; @@ -581,7 +579,7 @@ public boolean isAimedCorrectly(ShotMode shotMode) { */ public void targetExitPitch(Angle goalPitch) { this.requestedAction = HoodAction.TargetExitPitch; - this.goalExitPitch.mut_replace(goalPitch); + this.goalExitPitch = goalPitch; } /** @@ -596,6 +594,6 @@ public void targetExitPitch(Angle goalPitch) { */ public void targetAngleRadians(double angleRadians) { this.requestedAction = HoodAction.TargetAngle; - this.goalAngle.mut_replace(angleRadians, Radians); + this.goalAngle = new Angle(angleRadians, 1.0, Radians); } } diff --git a/src/main/java/frc/robot/subsystems/hopper/HopperSubsystem.java b/src/main/java/frc/robot/subsystems/hopper/HopperSubsystem.java index 3ab661dd..2584dcfc 100644 --- a/src/main/java/frc/robot/subsystems/hopper/HopperSubsystem.java +++ b/src/main/java/frc/robot/subsystems/hopper/HopperSubsystem.java @@ -1,10 +1,10 @@ package frc.robot.subsystems.hopper; -import static edu.wpi.first.units.Units.Amps; -import static edu.wpi.first.units.Units.RPM; -import static edu.wpi.first.units.Units.RadiansPerSecond; -import static edu.wpi.first.units.Units.Seconds; -import static edu.wpi.first.units.Units.Volts; +import static org.wpilib.units.Units.Amps; +import static org.wpilib.units.Units.RPM; +import static org.wpilib.units.Units.RadiansPerSecond; +import static org.wpilib.units.Units.Seconds; +import static org.wpilib.units.Units.Volts; import coppercore.controls.state_machine.StateMachine; import coppercore.math.Lazy; @@ -18,13 +18,13 @@ import coppercore.wpilib_interface.tuning.TuningModeHelper.MotorTuningMode; import coppercore.wpilib_interface.tuning.TuningModeHelper.TunableMotor; import coppercore.wpilib_interface.tuning.TuningModeHelper.TunableMotorConfiguration; -import edu.wpi.first.math.filter.Debouncer; -import edu.wpi.first.math.filter.Debouncer.DebounceType; -import edu.wpi.first.units.AngularVelocityUnit; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.units.measure.Voltage; -import edu.wpi.first.wpilibj.RobotController; -import edu.wpi.first.wpilibj.Timer; +import org.wpilib.math.filter.Debouncer; +import org.wpilib.math.filter.Debouncer.DebounceType; +import org.wpilib.units.AngularVelocityUnit; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.units.measure.Voltage; +import org.wpilib.system.RobotController; +import org.wpilib.system.Timer; import frc.robot.constants.JsonConstants; import frc.robot.subsystems.hopper.HopperState.DejamState; import frc.robot.subsystems.hopper.HopperState.IdleState; @@ -116,7 +116,7 @@ public HopperSubsystem(MotorIO motor) { @Override public void monitoredPeriodic() { - long startTimeUs = RobotController.getFPGATime(); + long startTimeUs = RobotController.getTime(); motor.updateInputs(inputs); @@ -126,7 +126,7 @@ public void monitoredPeriodic() { Logger.recordOutput("Hopper/State", stateMachine.getCurrentState().getName()); stateMachine.periodic(); - long endTimeUs = RobotController.getFPGATime(); + long endTimeUs = RobotController.getTime(); if (JsonConstants.featureFlags.logPeriodicTiming) { Logger.recordOutput("PeriodicTime/hopperMs", (endTimeUs - startTimeUs) / 1000.0); } diff --git a/src/main/java/frc/robot/subsystems/indexer/IndexerSubsystem.java b/src/main/java/frc/robot/subsystems/indexer/IndexerSubsystem.java index 0f827cec..adfa8a9b 100644 --- a/src/main/java/frc/robot/subsystems/indexer/IndexerSubsystem.java +++ b/src/main/java/frc/robot/subsystems/indexer/IndexerSubsystem.java @@ -1,8 +1,8 @@ package frc.robot.subsystems.indexer; -import static edu.wpi.first.units.Units.RPM; -import static edu.wpi.first.units.Units.RadiansPerSecond; -import static edu.wpi.first.units.Units.Seconds; +import static org.wpilib.units.Units.RPM; +import static org.wpilib.units.Units.RadiansPerSecond; +import static org.wpilib.units.Units.Seconds; import coppercore.controls.state_machine.StateMachine; import coppercore.math.Lazy; @@ -16,10 +16,10 @@ import coppercore.wpilib_interface.tuning.TuningModeHelper.MotorTuningMode; import coppercore.wpilib_interface.tuning.TuningModeHelper.TunableMotor; import coppercore.wpilib_interface.tuning.TuningModeHelper.TunableMotorConfiguration; -import edu.wpi.first.math.filter.Debouncer; -import edu.wpi.first.math.filter.Debouncer.DebounceType; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.wpilibj.RobotController; +import org.wpilib.math.filter.Debouncer; +import org.wpilib.math.filter.Debouncer.DebounceType; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.system.RobotController; import frc.robot.constants.JsonConstants; import frc.robot.subsystems.indexer.IndexerState.IdleState; import frc.robot.subsystems.indexer.IndexerState.ShootingState; @@ -132,7 +132,7 @@ public IndexerSubsystem(MotorIO motor) { @Override public void monitoredPeriodic() { - long startTimeUs = RobotController.getFPGATime(); + long startTimeUs = RobotController.getTime(); motor.updateInputs(inputs); Logger.processInputs("Indexer/inputs", inputs); @@ -142,7 +142,7 @@ public void monitoredPeriodic() { Logger.recordOutput("Indexer/State", stateMachine.getCurrentState().getName()); stateMachine.periodic(); - long endTimeUs = RobotController.getFPGATime(); + long endTimeUs = RobotController.getTime(); if (JsonConstants.featureFlags.logPeriodicTiming) { Logger.recordOutput("PeriodicTime/indexerMs", (endTimeUs - startTimeUs) / 1000.0); } diff --git a/src/main/java/frc/robot/subsystems/intake/IntakeState.java b/src/main/java/frc/robot/subsystems/intake/IntakeState.java index 5fecab8a..77094e08 100644 --- a/src/main/java/frc/robot/subsystems/intake/IntakeState.java +++ b/src/main/java/frc/robot/subsystems/intake/IntakeState.java @@ -1,8 +1,8 @@ package frc.robot.subsystems.intake; -import static edu.wpi.first.units.Units.Degrees; -import static edu.wpi.first.units.Units.RPM; -import static edu.wpi.first.units.Units.Radians; +import static org.wpilib.units.Units.Degrees; +import static org.wpilib.units.Units.RPM; +import static org.wpilib.units.Units.Radians; import coppercore.controls.state_machine.State; import coppercore.controls.state_machine.StateMachine; @@ -12,7 +12,7 @@ import coppercore.wpilib_interface.tuning.TuningModeHelper.MotorTuningMode; import coppercore.wpilib_interface.tuning.TuningModeHelper.TunableMotor; import coppercore.wpilib_interface.tuning.TuningModeHelper.TunableMotorConfiguration; -import edu.wpi.first.units.Units; +import org.wpilib.units.Units; import frc.robot.constants.JsonConstants; import java.util.function.Supplier; diff --git a/src/main/java/frc/robot/subsystems/intake/IntakeSubsystem.java b/src/main/java/frc/robot/subsystems/intake/IntakeSubsystem.java index bec8fc28..c951352b 100644 --- a/src/main/java/frc/robot/subsystems/intake/IntakeSubsystem.java +++ b/src/main/java/frc/robot/subsystems/intake/IntakeSubsystem.java @@ -1,9 +1,9 @@ package frc.robot.subsystems.intake; -import static edu.wpi.first.units.Units.Degrees; -import static edu.wpi.first.units.Units.Hertz; -import static edu.wpi.first.units.Units.RPM; -import static edu.wpi.first.units.Units.Radians; +import static org.wpilib.units.Units.Degrees; +import static org.wpilib.units.Units.Hertz; +import static org.wpilib.units.Units.RPM; +import static org.wpilib.units.Units.Radians; import coppercore.controls.state_machine.StateMachine; import coppercore.monitors.TotalCurrentCalculator; @@ -12,12 +12,12 @@ import coppercore.wpilib_interface.subsystems.motors.MotorIO; import coppercore.wpilib_interface.subsystems.motors.MotorInputsAutoLogged; import coppercore.wpilib_interface.tuning.TestModeManager; -import edu.wpi.first.math.util.Units; -import edu.wpi.first.units.measure.Angle; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.units.measure.Voltage; -import edu.wpi.first.wpilibj.DriverStation; -import edu.wpi.first.wpilibj.RobotController; +import org.wpilib.math.util.Units; +import org.wpilib.units.measure.Angle; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.units.measure.Voltage; +import org.wpilib.driverstation.internal.DriverStationBackend; +import org.wpilib.system.RobotController; import frc.robot.constants.JsonConstants; import frc.robot.util.StateMachineDump; import java.util.List; @@ -124,7 +124,7 @@ public IntakeSubsystem( // ### Homing Button Transitions IntakeState.waitForButtonState.whenFinished().transitionTo(IntakeState.controlToPositionState); IntakeState.waitForButtonState - .when(DriverStation::isEnabled, "When robot is enabled and button has not been pressed") + .when(DriverStationBackend::isEnabled, "When robot is enabled and button has not been pressed") .transitionTo(IntakeState.homingWaitForMovementState); // ### Wait for movement transitions @@ -132,7 +132,7 @@ public IntakeSubsystem( // the wait for button state to wait for the operator to re-enable the robot // and restart the homing process. IntakeState.homingWaitForMovementState - .when(DriverStation::isDisabled, "When robot is disabled during homing") + .when(DriverStationBackend::isDisabled, "When robot is disabled during homing") .transitionTo(IntakeState.waitForButtonState); // If the mechanism starts moving, we assume that it is has started the homing // process properly and we transition to the homing wait for stop moving state @@ -151,7 +151,7 @@ public IntakeSubsystem( // the wait for button state to wait for the operator to re-enable the robot // and restart the homing process. IntakeState.homingWaitForStopMovingState - .when(DriverStation::isDisabled, "When robot is disabled during homing") + .when(DriverStationBackend::isDisabled, "When robot is disabled during homing") .transitionTo(IntakeState.waitForButtonState); // If the mechanism starts moving, we assume that we have started the homing // process properly and so we wait for it to stop moving by hitting a hard @@ -216,7 +216,7 @@ public void applyHoldVoltage() { @Override public void monitoredPeriodic() { - long startTimeUs = RobotController.getFPGATime(); + long startTimeUs = RobotController.getTime(); pivotMotorIO.updateInputs(pivotInputs); rollersLeadMotorIO.updateInputs(rollerLeadMotorInputs); @@ -251,7 +251,7 @@ public void monitoredPeriodic() { // at the end of the periodic rollersFollowerMotorIO.follow(JsonConstants.canBusAssignment.intakeRollersLeadMotorId, false); - long endTimeUs = RobotController.getFPGATime(); + long endTimeUs = RobotController.getTime(); if (JsonConstants.featureFlags.logPeriodicTiming) { Logger.recordOutput("PeriodicTime/IntakeMs", (endTimeUs - startTimeUs) / 1000.0); } diff --git a/src/main/java/frc/robot/subsystems/shooter/ShooterSubsystem.java b/src/main/java/frc/robot/subsystems/shooter/ShooterSubsystem.java index f077683d..836776e6 100644 --- a/src/main/java/frc/robot/subsystems/shooter/ShooterSubsystem.java +++ b/src/main/java/frc/robot/subsystems/shooter/ShooterSubsystem.java @@ -1,12 +1,12 @@ package frc.robot.subsystems.shooter; -import static edu.wpi.first.units.Units.Amps; -import static edu.wpi.first.units.Units.RPM; -import static edu.wpi.first.units.Units.RadiansPerSecond; -import static edu.wpi.first.units.Units.RotationsPerSecondPerSecond; -import static edu.wpi.first.units.Units.Second; -import static edu.wpi.first.units.Units.Seconds; -import static edu.wpi.first.units.Units.Volts; +import static org.wpilib.units.Units.Amps; +import static org.wpilib.units.Units.RPM; +import static org.wpilib.units.Units.RadiansPerSecond; +import static org.wpilib.units.Units.RotationsPerSecondPerSecond; +import static org.wpilib.units.Units.Second; +import static org.wpilib.units.Units.Seconds; +import static org.wpilib.units.Units.Volts; import coppercore.controls.state_machine.StateMachine; import coppercore.math.Lazy; @@ -19,15 +19,14 @@ import coppercore.wpilib_interface.subsystems.motors.profile.MotionProfileConfig; import coppercore.wpilib_interface.tuning.LoggedTunablePIDGains; import coppercore.wpilib_interface.tuning.TestModeManager; -import edu.wpi.first.math.filter.Debouncer; -import edu.wpi.first.math.filter.Debouncer.DebounceType; -import edu.wpi.first.math.util.Units; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.units.measure.MutAngularVelocity; -import edu.wpi.first.units.measure.Voltage; -import edu.wpi.first.wpilibj.DriverStation; -import edu.wpi.first.wpilibj.RobotController; -import edu.wpi.first.wpilibj.Timer; +import org.wpilib.math.filter.Debouncer; +import org.wpilib.math.filter.Debouncer.DebounceType; +import org.wpilib.math.util.Units; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.units.measure.Voltage; +import org.wpilib.driverstation.internal.DriverStationBackend; +import org.wpilib.system.RobotController; +import org.wpilib.system.Timer; import frc.robot.CoordinationLayer.ShotMode; import frc.robot.DependencyOrderedExecutor; import frc.robot.DependencyOrderedExecutor.ActionKey; @@ -97,7 +96,7 @@ private enum ShooterAction { Lazy shooterTuningVolts; // State variables - private final MutAngularVelocity targetVelocity = RPM.mutable(0.0); + private AngularVelocity targetVelocity = RPM.of(0.0); @AutoLogOutput(key = "Shooter/requestedAction") private ShooterAction requestedAction = ShooterAction.Coast; @@ -206,7 +205,7 @@ private void updateInputs() { @Override public void monitoredPeriodic() { - long startTimeUs = RobotController.getFPGATime(); + long startTimeUs = RobotController.getTime(); Logger.recordOutput("Shooter/TargetVelocityRadPerSec", targetVelocity.in(RadiansPerSecond)); @@ -228,7 +227,7 @@ public void monitoredPeriodic() { JsonConstants.shooterConstants.invertFollower); } - long endTimeUs = RobotController.getFPGATime(); + long endTimeUs = RobotController.getTime(); if (JsonConstants.featureFlags.logPeriodicTiming) { Logger.recordOutput("PeriodicTime/ShooterMs", (endTimeUs - startTimeUs) / 1000.0); } @@ -319,7 +318,7 @@ protected void testPeriodic() { leadMotor.controlOpenLoopVoltage(Volts.of(shooterTuningVolts.get().getAsDouble())); } case ShooterFFCharacterization -> { - if (DriverStation.isEnabled()) { + if (DriverStationBackend.isEnabled()) { Voltage characterizationVoltage = (Voltage) JsonConstants.shooterConstants.characterizationRampRate.times( @@ -364,7 +363,7 @@ protected void coast() { * @param velocityRPM A double containing target velocity, in RPM */ public void setTargetVelocityRPM(double velocityRPM) { - targetVelocity.mut_replace(velocityRPM, RPM); + targetVelocity = new AngularVelocity(velocityRPM, 1, RPM); requestedAction = ShooterAction.ControlVelocity; } diff --git a/src/main/java/frc/robot/subsystems/transferroller/TransferRollerSubsystem.java b/src/main/java/frc/robot/subsystems/transferroller/TransferRollerSubsystem.java index 859c70a7..cdd8acf3 100644 --- a/src/main/java/frc/robot/subsystems/transferroller/TransferRollerSubsystem.java +++ b/src/main/java/frc/robot/subsystems/transferroller/TransferRollerSubsystem.java @@ -1,9 +1,9 @@ package frc.robot.subsystems.transferroller; -import static edu.wpi.first.units.Units.Amps; -import static edu.wpi.first.units.Units.RPM; -import static edu.wpi.first.units.Units.RadiansPerSecond; -import static edu.wpi.first.units.Units.Seconds; +import static org.wpilib.units.Units.Amps; +import static org.wpilib.units.Units.RPM; +import static org.wpilib.units.Units.RadiansPerSecond; +import static org.wpilib.units.Units.Seconds; import coppercore.controls.state_machine.StateMachine; import coppercore.math.Lazy; @@ -16,11 +16,11 @@ import coppercore.wpilib_interface.tuning.TuningModeHelper.MotorTuningMode; import coppercore.wpilib_interface.tuning.TuningModeHelper.TunableMotor; import coppercore.wpilib_interface.tuning.TuningModeHelper.TunableMotorConfiguration; -import edu.wpi.first.math.filter.Debouncer; -import edu.wpi.first.math.filter.Debouncer.DebounceType; -import edu.wpi.first.units.Units; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.wpilibj.RobotController; +import org.wpilib.math.filter.Debouncer; +import org.wpilib.math.filter.Debouncer.DebounceType; +import org.wpilib.units.Units; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.system.RobotController; import frc.robot.constants.JsonConstants; import frc.robot.subsystems.transferroller.TransferRollerState.DeJamState; import frc.robot.subsystems.transferroller.TransferRollerState.IdleState; @@ -138,7 +138,7 @@ public TransferRollerSubsystem(MotorIO motor) { @Override public void monitoredPeriodic() { - long startTimeUs = RobotController.getFPGATime(); + long startTimeUs = RobotController.getTime(); motor.updateInputs(inputs); Logger.processInputs("TransferRoller/inputs", inputs); @@ -146,7 +146,7 @@ public void monitoredPeriodic() { Logger.recordOutput("TransferRoller/State", stateMachine.getCurrentState().getName()); stateMachine.periodic(); - long endTimeUs = RobotController.getFPGATime(); + long endTimeUs = RobotController.getTime(); if (JsonConstants.featureFlags.logPeriodicTiming) { Logger.recordOutput("PeriodicTime/TransferRollerMs", (endTimeUs - startTimeUs) / 1000.0); } diff --git a/src/main/java/frc/robot/subsystems/turret/TurretState.java b/src/main/java/frc/robot/subsystems/turret/TurretState.java index c09d0644..b9b457b8 100644 --- a/src/main/java/frc/robot/subsystems/turret/TurretState.java +++ b/src/main/java/frc/robot/subsystems/turret/TurretState.java @@ -1,11 +1,11 @@ package frc.robot.subsystems.turret; -import static edu.wpi.first.units.Units.Degrees; -import static edu.wpi.first.units.Units.RadiansPerSecond; +import static org.wpilib.units.Units.Degrees; +import static org.wpilib.units.Units.RadiansPerSecond; import coppercore.controls.state_machine.State; import coppercore.controls.state_machine.StateMachine; -import edu.wpi.first.units.AngularVelocityUnit; +import org.wpilib.units.AngularVelocityUnit; import frc.robot.constants.JsonConstants; /** diff --git a/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java b/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java index 498eccba..1cb41e6c 100644 --- a/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java +++ b/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java @@ -1,14 +1,14 @@ package frc.robot.subsystems.turret; -import static edu.wpi.first.units.Units.Amps; -import static edu.wpi.first.units.Units.Degrees; -import static edu.wpi.first.units.Units.Hertz; -import static edu.wpi.first.units.Units.Radians; -import static edu.wpi.first.units.Units.RadiansPerSecond; -import static edu.wpi.first.units.Units.RotationsPerSecond; -import static edu.wpi.first.units.Units.RotationsPerSecondPerSecond; -import static edu.wpi.first.units.Units.Seconds; -import static edu.wpi.first.units.Units.Volts; +import static org.wpilib.units.Units.Amps; +import static org.wpilib.units.Units.Degrees; +import static org.wpilib.units.Units.Hertz; +import static org.wpilib.units.Units.Radians; +import static org.wpilib.units.Units.RadiansPerSecond; +import static org.wpilib.units.Units.RotationsPerSecond; +import static org.wpilib.units.Units.RotationsPerSecondPerSecond; +import static org.wpilib.units.Units.Seconds; +import static org.wpilib.units.Units.Volts; import coppercore.controls.state_machine.StateMachine; import coppercore.math.AngleUtil; @@ -21,12 +21,13 @@ import coppercore.wpilib_interface.subsystems.motors.MotorInputsAutoLogged; import coppercore.wpilib_interface.subsystems.motors.profile.MotionProfileConfig; import coppercore.wpilib_interface.tuning.TestModeManager; -import edu.wpi.first.math.geometry.Rotation2d; -import edu.wpi.first.math.interpolation.InterpolatingDoubleTreeMap; -import edu.wpi.first.units.measure.Angle; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.wpilibj.DriverStation; -import edu.wpi.first.wpilibj.RobotController; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.math.interpolation.InterpolatingDoubleTreeMap; +import org.wpilib.units.measure.Angle; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.internal.DriverStationBackend; +import org.wpilib.system.RobotController; import frc.robot.Constants; import frc.robot.CoordinationLayer.ShotMode; import frc.robot.DependencyOrderedExecutor; @@ -164,7 +165,7 @@ public TurretSubsystem(DependencyOrderedExecutor dependencyOrderedExecutor, Moto .whenTimeout(Seconds.of(1.0)) .transitionTo(homingWaitForButtonChirpState); homingWaitForButtonState - .when(turret -> DriverStation.isEnabled(), "Robot is enabled") + .when(turret -> DriverStationBackend.isEnabled(), "Robot is enabled") .transitionTo(homingWaitForMovementState); homingWaitForButtonChirpState.whenFinished().transitionTo(idleState); @@ -172,7 +173,7 @@ public TurretSubsystem(DependencyOrderedExecutor dependencyOrderedExecutor, Moto .whenTimeout(Seconds.of(0.5)) .transitionTo(homingWaitForButtonState); homingWaitForButtonChirpState - .when(turret -> DriverStation.isEnabled(), "Robot is enabled") + .when(turret -> DriverStationBackend.isEnabled(), "Robot is enabled") .transitionTo(homingWaitForMovementState); homingWaitForMovementState.whenFinished().transitionTo(homingWaitForStoppingState); @@ -301,12 +302,12 @@ public void updateInputs() { @Override public void monitoredPeriodic() { - long startTimeUs = RobotController.getFPGATime(); + long startTimeUs = RobotController.getTime(); Logger.recordOutput("Turret/State", stateMachine.getCurrentState().getName()); stateMachine.periodic(); - long endTimeUs = RobotController.getFPGATime(); + long endTimeUs = RobotController.getTime(); if (JsonConstants.featureFlags.logPeriodicTiming) { Logger.recordOutput("PeriodicTime/TurretMs", (endTimeUs - startTimeUs) / 1000.0); } @@ -508,13 +509,13 @@ private void controlToTurretCentricPositionRaw(Angle goalAngleTurretCentric) { */ protected void controlToGoalHeading() { Rotation2d robotRelativeHeading = goalTurretHeading.minus(dependencies.robotHeading); - Rotation2d turretRelativeHeading = - AngleUtil.normalizeHeading( - robotRelativeHeading.plus( - new Rotation2d(JsonConstants.turretConstants.headingToTurretAngle))); + // Rotation2d turretRelativeHeading = + // AngleUtil.normalizeHeading( + // robotRelativeHeading.plus( + // new Rotation2d(JsonConstants.turretConstants.headingToTurretAngle))); - Angle adjustedGoalAngle = applyGoalAngleOffset(turretRelativeHeading.getMeasure()); - controlToTurretCentricPositionRaw(adjustedGoalAngle); + // Angle adjustedGoalAngle = applyGoalAngleOffset(turretRelativeHeading.getMeasure()); + // controlToTurretCentricPositionRaw(adjustedGoalAngle); } private Angle getGoalAngleOffset(Angle goalAngleTurretCentric) { @@ -533,15 +534,16 @@ private Angle applyGoalAngleOffset(Angle goalAngleTurretCentric) { private Rotation2d getAdjustedGoalTurretHeadingFieldCentric() { Rotation2d robotRelativeHeading = goalTurretHeading.minus(dependencies.robotHeading); - Rotation2d turretRelativeHeading = - AngleUtil.normalizeHeading( - robotRelativeHeading.plus( - new Rotation2d(JsonConstants.turretConstants.headingToTurretAngle))); - - Angle adjustedTurretAngle = applyGoalAngleOffset(turretRelativeHeading.getMeasure()); - return new Rotation2d( - adjustedTurretAngle.minus(JsonConstants.turretConstants.headingToTurretAngle)) - .plus(dependencies.robotHeading); + // Rotation2d turretRelativeHeading = + // AngleUtil.normalizeHeading( + // robotRelativeHeading.plus( + // new Rotation2d(JsonConstants.turretConstants.headingToTurretAngle))); + + // Angle adjustedTurretAngle = applyGoalAngleOffset(turretRelativeHeading.getMeasure()); + // return new Rotation2d( + // adjustedTurretAngle.minus(JsonConstants.turretConstants.headingToTurretAngle)) + // .plus(dependencies.robotHeading); + return new Rotation2d(); // TO BE REMOVED } /** diff --git a/src/main/java/frc/robot/util/CommandState.java b/src/main/java/frc/robot/util/CommandState.java index f45968b1..f304a18e 100644 --- a/src/main/java/frc/robot/util/CommandState.java +++ b/src/main/java/frc/robot/util/CommandState.java @@ -2,7 +2,7 @@ import coppercore.controls.state_machine.State; import coppercore.controls.state_machine.StateMachine; -import edu.wpi.first.wpilibj2.command.Command; +import org.wpilib.command2.Command; // Copilot used to help write the docs for this class diff --git a/src/main/java/frc/robot/util/Elastic.java b/src/main/java/frc/robot/util/Elastic.java index 9e5c07bc..102558eb 100644 --- a/src/main/java/frc/robot/util/Elastic.java +++ b/src/main/java/frc/robot/util/Elastic.java @@ -8,24 +8,25 @@ package frc.robot.util; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import edu.wpi.first.networktables.NetworkTableInstance; -import edu.wpi.first.networktables.PubSubOption; -import edu.wpi.first.networktables.StringPublisher; -import edu.wpi.first.networktables.StringTopic; +import io.avaje.jsonb.Json; +import io.avaje.jsonb.JsonType; +import io.avaje.jsonb.Jsonb; +import org.wpilib.networktables.NetworkTableInstance; +import org.wpilib.networktables.PubSubOption; +import org.wpilib.networktables.StringPublisher; +import org.wpilib.networktables.StringTopic; public final class Elastic { private static final StringTopic notificationTopic = NetworkTableInstance.getDefault().getStringTopic("/Elastic/RobotNotifications"); private static final StringPublisher notificationPublisher = - notificationTopic.publish(PubSubOption.sendAll(true), PubSubOption.keepDuplicates(true)); + notificationTopic.publish(new PubSubOption.SendAll(true), new PubSubOption.KeepDuplicates(true)); private static final StringTopic selectedTabTopic = NetworkTableInstance.getDefault().getStringTopic("/Elastic/SelectedTab"); private static final StringPublisher selectedTabPublisher = - selectedTabTopic.publish(PubSubOption.keepDuplicates(true)); - private static final ObjectMapper objectMapper = new ObjectMapper(); + selectedTabTopic.publish(new PubSubOption.KeepDuplicates(true)); + private static final Jsonb jsonb = Jsonb.builder().serializeNulls(true).build(); + private static final JsonType notificationJson = jsonb.type(Notification.class); /** * Represents the possible levels of notifications for the Elastic dashboard. These levels are @@ -48,8 +49,8 @@ public enum NotificationLevel { */ public static void sendNotification(Notification notification) { try { - notificationPublisher.set(objectMapper.writeValueAsString(notification)); - } catch (JsonProcessingException e) { + notificationPublisher.set(notificationJson.toJson(notification)); + } catch (RuntimeException e) { e.printStackTrace(); } } @@ -82,23 +83,19 @@ public static void selectTab(int tabIndex) { * properties such as level, title, description, display time, and dimensions to control how the * notification is displayed on the dashboard. */ + @Json public static class Notification { - @JsonProperty("level") private NotificationLevel level; - @JsonProperty("title") private String title; - @JsonProperty("description") private String description; - @JsonProperty("displayTime") + @Json.Property("displayTime") private int displayTimeMillis; - @JsonProperty("width") private double width; - @JsonProperty("height") private double height; /** diff --git a/src/main/java/frc/robot/util/LocalADStarAK.java b/src/main/java/frc/robot/util/LocalADStarAK.java index 846dd043..82a51a07 100644 --- a/src/main/java/frc/robot/util/LocalADStarAK.java +++ b/src/main/java/frc/robot/util/LocalADStarAK.java @@ -13,8 +13,8 @@ import com.pathplanner.lib.path.PathPoint; import com.pathplanner.lib.pathfinding.LocalADStar; import com.pathplanner.lib.pathfinding.Pathfinder; -import edu.wpi.first.math.Pair; -import edu.wpi.first.math.geometry.Translation2d; +import org.wpilib.math.util.Pair; +import org.wpilib.math.geometry.Translation2d; import java.util.ArrayList; import java.util.Collections; import java.util.List; diff --git a/src/main/java/frc/robot/util/json/JSONAPTarget.java b/src/main/java/frc/robot/util/json/JSONAPTarget.java index 5ab6d8d5..05251512 100644 --- a/src/main/java/frc/robot/util/json/JSONAPTarget.java +++ b/src/main/java/frc/robot/util/json/JSONAPTarget.java @@ -2,9 +2,9 @@ import com.therekrab.autopilot.APTarget; import coppercore.parameter_tools.json.helpers.JSONObject; -import edu.wpi.first.math.geometry.Pose2d; -import edu.wpi.first.math.geometry.Rotation2d; -import edu.wpi.first.units.measure.Distance; +import org.wpilib.math.geometry.Pose2d; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.units.measure.Distance; import java.lang.reflect.Constructor; public class JSONAPTarget extends JSONObject { diff --git a/src/main/java/frc/robot/util/json/JSONMotionProfileConfig.java b/src/main/java/frc/robot/util/json/JSONMotionProfileConfig.java index e9670742..1c44cbdd 100644 --- a/src/main/java/frc/robot/util/json/JSONMotionProfileConfig.java +++ b/src/main/java/frc/robot/util/json/JSONMotionProfileConfig.java @@ -3,13 +3,13 @@ import coppercore.parameter_tools.json.helpers.JSONObject; import coppercore.wpilib_interface.subsystems.motors.profile.MotionProfileConfig; import coppercore.wpilib_interface.subsystems.motors.profile.MutableMotionProfileConfig; -import edu.wpi.first.units.AngularAccelerationUnit; -import edu.wpi.first.units.AngularVelocityUnit; -import edu.wpi.first.units.VoltageUnit; -import edu.wpi.first.units.measure.AngularAcceleration; -import edu.wpi.first.units.measure.AngularVelocity; -import edu.wpi.first.units.measure.Per; -import edu.wpi.first.units.measure.Velocity; +import org.wpilib.units.AngularAccelerationUnit; +import org.wpilib.units.AngularVelocityUnit; +import org.wpilib.units.VoltageUnit; +import org.wpilib.units.measure.AngularAcceleration; +import org.wpilib.units.measure.AngularVelocity; +import org.wpilib.units.measure.Per; +import org.wpilib.units.measure.Velocity; import java.lang.reflect.Constructor; public class JSONMotionProfileConfig extends JSONObject { diff --git a/src/main/java/frc/robot/util/littletonUtil/GeomUtil.java b/src/main/java/frc/robot/util/littletonUtil/GeomUtil.java index a64630ca..159a88a5 100644 --- a/src/main/java/frc/robot/util/littletonUtil/GeomUtil.java +++ b/src/main/java/frc/robot/util/littletonUtil/GeomUtil.java @@ -9,18 +9,18 @@ // license that can be found in the LICENSE file at // the root directory of this project. -import static edu.wpi.first.units.Units.Degrees; - -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.Rotation3d; -import edu.wpi.first.math.geometry.Transform2d; -import edu.wpi.first.math.geometry.Transform3d; -import edu.wpi.first.math.geometry.Translation2d; -import edu.wpi.first.math.geometry.Twist2d; -import edu.wpi.first.math.kinematics.ChassisSpeeds; -import edu.wpi.first.units.measure.Angle; +import static org.wpilib.units.Units.Degrees; + +import org.wpilib.math.geometry.Pose2d; +import org.wpilib.math.geometry.Pose3d; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.math.geometry.Rotation3d; +import org.wpilib.math.geometry.Transform2d; +import org.wpilib.math.geometry.Transform3d; +import org.wpilib.math.geometry.Translation2d; +import org.wpilib.math.geometry.Twist2d; +import org.wpilib.math.kinematics.ChassisVelocities; +import org.wpilib.units.measure.Angle; /** Geometry utilities for working with translations, rotations, transforms, and poses. */ public class GeomUtil { @@ -129,9 +129,9 @@ public static Pose3d toPose3d(Transform3d transform) { * @param speeds The original translation * @return The resulting translation */ - public static Twist2d toTwist2d(ChassisSpeeds speeds) { + public static Twist2d toTwist2d(ChassisVelocities speeds) { return new Twist2d( - speeds.vxMetersPerSecond, speeds.vyMetersPerSecond, speeds.omegaRadiansPerSecond); + speeds.vx, speeds.vy, speeds.omega); } /** diff --git a/src/main/java/frc/robot/util/littletonUtil/PoseEstimator.java b/src/main/java/frc/robot/util/littletonUtil/PoseEstimator.java index dd2fe7eb..61db60da 100644 --- a/src/main/java/frc/robot/util/littletonUtil/PoseEstimator.java +++ b/src/main/java/frc/robot/util/littletonUtil/PoseEstimator.java @@ -10,14 +10,14 @@ package frc.robot.util.littletonUtil; -import edu.wpi.first.math.Matrix; -import edu.wpi.first.math.Nat; -import edu.wpi.first.math.VecBuilder; -import edu.wpi.first.math.geometry.Pose2d; -import edu.wpi.first.math.geometry.Twist2d; -import edu.wpi.first.math.numbers.N1; -import edu.wpi.first.math.numbers.N3; -import edu.wpi.first.wpilibj.Timer; +import org.wpilib.math.linalg.Matrix; +import org.wpilib.math.util.Nat; +import org.wpilib.math.linalg.VecBuilder; +import org.wpilib.math.geometry.Pose2d; +import org.wpilib.math.geometry.Twist2d; +import org.wpilib.math.numbers.N1; +import org.wpilib.math.numbers.N3; +import org.wpilib.system.Timer; import java.util.ArrayList; import java.util.Comparator; import java.util.List; @@ -124,12 +124,12 @@ private void update() { private static record PoseUpdate(Twist2d twist, ArrayList visionUpdates) { public Pose2d apply(Pose2d lastPose, Matrix q) { // Apply drive twist - var pose = lastPose.exp(twist); + var pose = lastPose.plus(twist.exp()); // Apply vision updates for (VisionUpdate visionUpdate : visionUpdates) { // Calculate Kalman gains based on std devs - // (https://github.com/wpilibsuite/allwpilib/blob/main/wpimath/src/main/java/edu/wpi/first/math/estimator/) + // (https://github.com/wpilibsuite/allwpilib/blob/main/wpimath/src/main/java/org.wpilib.math/estimator/) Matrix visionK = new Matrix<>(Nat.N3(), Nat.N3()); var r = new double[3]; for (int i = 0; i < 3; ++i) { @@ -145,7 +145,7 @@ public Pose2d apply(Pose2d lastPose, Matrix q) { } // Calculate twist between current and vision pose - var visionTwist = pose.log(visionUpdate.pose()); + var visionTwist = visionUpdate.pose().minus(pose).log(); // Multiply by Kalman gain matrix var twistMatrix = @@ -153,8 +153,8 @@ public Pose2d apply(Pose2d lastPose, Matrix q) { // Apply twist pose = - pose.exp( - new Twist2d(twistMatrix.get(0, 0), twistMatrix.get(1, 0), twistMatrix.get(2, 0))); + pose.plus( + new Twist2d(twistMatrix.get(0, 0), twistMatrix.get(1, 0), twistMatrix.get(2, 0)).exp()); } return pose; diff --git a/vendordeps/AdvantageKit.json b/vendordeps/AdvantageKit.json index 469ae542..177ee85c 100644 --- a/vendordeps/AdvantageKit.json +++ b/vendordeps/AdvantageKit.json @@ -1,35 +1,35 @@ { - "fileName": "AdvantageKit.json", - "name": "AdvantageKit", - "version": "26.0.2", - "uuid": "d820cc26-74e3-11ec-90d6-0242ac120003", - "frcYear": "2026", - "mavenUrls": [ - "https://frcmaven.wpi.edu/artifactory/littletonrobotics-mvn-release/" - ], - "jsonUrl": "https://github.com/Mechanical-Advantage/AdvantageKit/releases/latest/download/AdvantageKit.json", - "javaDependencies": [ - { - "groupId": "org.littletonrobotics.akit", - "artifactId": "akit-java", - "version": "26.0.2" - } - ], - "jniDependencies": [ - { - "groupId": "org.littletonrobotics.akit", - "artifactId": "akit-wpilibio", - "version": "26.0.2", - "skipInvalidPlatforms": false, - "isJar": false, - "validPlatforms": [ - "linuxathena", - "linuxx86-64", - "linuxarm64", - "osxuniversal", - "windowsx86-64" - ] - } - ], - "cppDependencies": [] -} + "fileName": "AdvantageKit.json", + "name": "AdvantageKit", + "version": "27.0.0-alpha-4", + "uuid": "d820cc26-74e3-11ec-90d6-0242ac120003", + "wpilibYear": "2027_alpha5", + "mavenUrls": [ + "https://frcmaven.wpi.edu/artifactory/littletonrobotics-mvn-release/" + ], + "jsonUrl": "https://github.com/Mechanical-Advantage/AdvantageKit/releases/latest/download/AdvantageKit.json", + "javaDependencies": [ + { + "groupId": "org.littletonrobotics.akit", + "artifactId": "akit-java", + "version": "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/Autopilot.json b/vendordeps/Autopilot.json deleted file mode 100644 index 3575aeb2..00000000 --- a/vendordeps/Autopilot.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "Autopilot", - "uuid": "4e922d47-9954-4db5-929f-c708cc62e152", - "fileName": "Autopilot.json", - "version": "1.5.0", - "frcYear": "2026", - "jsonUrl": "https://therekrab.github.io/autopilot/vendordep.json", - "mavenUrls": [ - "https://jitpack.io" - ], - "javaDependencies": [ - { - "groupId": "com.github.therekrab", - "artifactId": "autopilot", - "version": "1.5.0" - } - ], - "cppDependencies": [], - "jniDependencies": [] -} diff --git a/vendordeps/CommandsV2.json b/vendordeps/CommandsV2.json new file mode 100644 index 00000000..984c221c --- /dev/null +++ b/vendordeps/CommandsV2.json @@ -0,0 +1,46 @@ +{ + "fileName": "CommandsV2.json", + "name": "Commands V2", + "version": "1.0.0", + "uuid": "111e20f7-815e-48f8-9dd6-e675ce75b266", + "wpilibYear": "2027_alpha5", + "mavenUrls": [], + "jsonUrl": "", + "conflictsWith": [ + { + "uuid": "4decdc05-a056-46cf-9561-39449bbb01306", + "errorMessage": "Users can not have both Commands v2 and Commands v3 vendordeps in their robot program.", + "offlineFileName": "CommandsV3.json" + } + ], + "javaDependencies": [ + { + "groupId": "org.wpilib.commandsv2", + "artifactId": "commandsv2-java", + "version": "wpilib" + } + ], + "jniDependencies": [], + "cppDependencies": [ + { + "groupId": "org.wpilib.commandsv2", + "artifactId": "commandsv2-cpp", + "version": "wpilib", + "libName": "commandsv2", + "headerClassifier": "headers", + "sourcesClassifier": "sources", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxsystemcore", + "linuxathena", + "linuxarm32", + "linuxarm64", + "windowsx86-64", + "windowsx86", + "linuxx86-64", + "osxuniversal" + ] + } + ] +} \ No newline at end of file diff --git a/vendordeps/PathplannerLib.json b/vendordeps/PathplannerLib.json deleted file mode 100644 index 5f04ffa7..00000000 --- a/vendordeps/PathplannerLib.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "fileName": "PathplannerLib-2026.1.2.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" - ] - } - ] -} diff --git a/vendordeps/PathplannerLibSystemCoreAlpha.json b/vendordeps/PathplannerLibSystemCoreAlpha.json new file mode 100644 index 00000000..24d3c8c7 --- /dev/null +++ b/vendordeps/PathplannerLibSystemCoreAlpha.json @@ -0,0 +1,37 @@ +{ + "fileName": "PathplannerLibSystemCoreAlpha.json", + "name": "PathplannerLib", + "version": "2027.0.0-alpha-3", + "uuid": "1b42324f-17c6-4875-8e77-1c312bc8c786", + "wpilibYear": "2027_alpha5", + "mavenUrls": [ + "https://3015rangerrobotics.github.io/pathplannerlib/repo" + ], + "jsonUrl": "https://3015rangerrobotics.github.io/pathplannerlib/PathplannerLibSystemCoreAlpha.json", + "javaDependencies": [ + { + "groupId": "com.pathplanner.lib", + "artifactId": "PathplannerLib-java", + "version": "2027.0.0-alpha-3" + } + ], + "jniDependencies": [], + "cppDependencies": [ + { + "groupId": "com.pathplanner.lib", + "artifactId": "PathplannerLib-cpp", + "version": "2027.0.0-alpha-3", + "libName": "PathplannerLib", + "headerClassifier": "headers", + "sharedLibrary": false, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal", + "linuxsystemcore", + "linuxarm64" + ] + } + ] +} \ No newline at end of file diff --git a/vendordeps/Phoenix6-26.1.2.json b/vendordeps/Phoenix6-26.1.2.json deleted file mode 100644 index d33c02b6..00000000 --- a/vendordeps/Phoenix6-26.1.2.json +++ /dev/null @@ -1,449 +0,0 @@ -{ - "fileName": "Phoenix6-26.1.2.json", - "name": "CTRE-Phoenix (v6)", - "version": "26.1.2", - "frcYear": "2026", - "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", - "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" - } - ], - "javaDependencies": [ - { - "groupId": "com.ctre.phoenix6", - "artifactId": "wpiapi-java", - "version": "26.1.2" - } - ], - "jniDependencies": [ - { - "groupId": "com.ctre.phoenix6", - "artifactId": "api-cpp", - "version": "26.1.2", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "linuxathena" - ], - "simMode": "hwsim" - }, - { - "groupId": "com.ctre.phoenix6", - "artifactId": "tools", - "version": "26.1.2", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "linuxathena" - ], - "simMode": "hwsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "api-cpp-sim", - "version": "26.1.2", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "tools-sim", - "version": "26.1.2", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simTalonSRX", - "version": "26.1.2", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simVictorSPX", - "version": "26.1.2", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simPigeonIMU", - "version": "26.1.2", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simProTalonFX", - "version": "26.1.2", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simProTalonFXS", - "version": "26.1.2", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simProCANcoder", - "version": "26.1.2", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simProPigeon2", - "version": "26.1.2", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simProCANrange", - "version": "26.1.2", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simProCANdi", - "version": "26.1.2", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simProCANdle", - "version": "26.1.2", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - } - ], - "cppDependencies": [ - { - "groupId": "com.ctre.phoenix6", - "artifactId": "wpiapi-cpp", - "version": "26.1.2", - "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": "26.1.2", - "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": "26.1.2", - "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": "26.1.2", - "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": "26.1.2", - "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": "26.1.2", - "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": "26.1.2", - "libName": "CTRE_SimPigeonIMU", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simProTalonFX", - "version": "26.1.2", - "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": "26.1.2", - "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": "26.1.2", - "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": "26.1.2", - "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": "26.1.2", - "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": "26.1.2", - "libName": "CTRE_SimProCANdi", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simProCANdle", - "version": "26.1.2", - "libName": "CTRE_SimProCANdle", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - } - ] -} diff --git a/vendordeps/Phoenix6-26.50.0-alpha-1.json b/vendordeps/Phoenix6-26.50.0-alpha-1.json new file mode 100644 index 00000000..f7db60ad --- /dev/null +++ b/vendordeps/Phoenix6-26.50.0-alpha-1.json @@ -0,0 +1,449 @@ +{ + "fileName": "Phoenix6-26.50.0-alpha-1.json", + "name": "CTRE-Phoenix (v6)", + "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-frc2027-latest.json", + "conflictsWith": [ + { + "uuid": "e7900d8d-826f-4dca-a1ff-182f658e98af", + "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.50.0-alpha-1" + } + ], + "jniDependencies": [ + { + "groupId": "com.ctre.phoenix6", + "artifactId": "api-cpp", + "version": "26.50.0-alpha-1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "linuxsystemcore" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6", + "artifactId": "tools", + "version": "26.50.0-alpha-1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "linuxsystemcore" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "api-cpp-sim", + "version": "26.50.0-alpha-1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "tools-sim", + "version": "26.50.0-alpha-1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simTalonSRX", + "version": "26.50.0-alpha-1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simVictorSPX", + "version": "26.50.0-alpha-1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simPigeonIMU", + "version": "26.50.0-alpha-1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProTalonFX", + "version": "26.50.0-alpha-1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProTalonFXS", + "version": "26.50.0-alpha-1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANcoder", + "version": "26.50.0-alpha-1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProPigeon2", + "version": "26.50.0-alpha-1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANrange", + "version": "26.50.0-alpha-1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANdi", + "version": "26.50.0-alpha-1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANdle", + "version": "26.50.0-alpha-1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + } + ], + "cppDependencies": [ + { + "groupId": "com.ctre.phoenix6", + "artifactId": "wpiapi-cpp", + "version": "26.50.0-alpha-1", + "libName": "CTRE_Phoenix6_WPI", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "linuxsystemcore" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6", + "artifactId": "tools", + "version": "26.50.0-alpha-1", + "libName": "CTRE_PhoenixTools", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "linuxsystemcore" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "wpiapi-cpp-sim", + "version": "26.50.0-alpha-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": "26.50.0-alpha-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": "26.50.0-alpha-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": "26.50.0-alpha-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": "26.50.0-alpha-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": "simProTalonFX", + "version": "26.50.0-alpha-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": "26.50.0-alpha-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": "26.50.0-alpha-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": "26.50.0-alpha-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": "26.50.0-alpha-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": "26.50.0-alpha-1", + "libName": "CTRE_SimProCANdi", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANdle", + "version": "26.50.0-alpha-1", + "libName": "CTRE_SimProCANdle", + "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 082b01dc..2861f9e2 100644 --- a/vendordeps/REVLib.json +++ b/vendordeps/REVLib.json @@ -1,133 +1,126 @@ { - "fileName": "REVLib.json", - "name": "REVLib", - "version": "2026.0.0", - "frcYear": "2026", - "uuid": "3f48eb8c-50fe-43a6-9cb7-44c86353c4cb", - "mavenUrls": [ - "https://maven.revrobotics.com/" - ], - "jsonUrl": "https://software-metadata.revrobotics.com/REVLib-2026.json", - "javaDependencies": [ - { - "groupId": "com.revrobotics.frc", - "artifactId": "REVLib-java", - "version": "2026.0.0" - } - ], - "jniDependencies": [ - { - "groupId": "com.revrobotics.frc", - "artifactId": "REVLib-driver", - "version": "2026.0.0", - "skipInvalidPlatforms": true, - "isJar": false, - "validPlatforms": [ - "windowsx86-64", - "linuxarm64", - "linuxx86-64", - "linuxathena", - "linuxarm32", - "osxuniversal" - ] - }, - { - "groupId": "com.revrobotics.frc", - "artifactId": "RevLibBackendDriver", - "version": "2026.0.0", - "skipInvalidPlatforms": true, - "isJar": false, - "validPlatforms": [ - "windowsx86-64", - "linuxarm64", - "linuxx86-64", - "linuxathena", - "linuxarm32", - "osxuniversal" - ] - }, - { - "groupId": "com.revrobotics.frc", - "artifactId": "RevLibWpiBackendDriver", - "version": "2026.0.0", - "skipInvalidPlatforms": true, - "isJar": false, - "validPlatforms": [ - "windowsx86-64", - "linuxarm64", - "linuxx86-64", - "linuxathena", - "linuxarm32", - "osxuniversal" - ] - } - ], - "cppDependencies": [ - { - "groupId": "com.revrobotics.frc", - "artifactId": "REVLib-cpp", - "version": "2026.0.0", - "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": "2026.0.0", - "libName": "REVLibDriver", - "headerClassifier": "headers", - "sharedLibrary": false, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxarm64", - "linuxx86-64", - "linuxathena", - "linuxarm32", - "osxuniversal" - ] - }, - { - "groupId": "com.revrobotics.frc", - "artifactId": "RevLibBackendDriver", - "version": "2026.0.0", - "libName": "BackendDriver", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxarm64", - "linuxx86-64", - "linuxathena", - "linuxarm32", - "osxuniversal" - ] - }, - { - "groupId": "com.revrobotics.frc", - "artifactId": "RevLibWpiBackendDriver", - "version": "2026.0.0", - "libName": "REVLibWpi", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxarm64", - "linuxx86-64", - "linuxathena", - "linuxarm32", - "osxuniversal" - ] - } - ] -} + "fileName": "REVLib.json", + "name": "REVLib", + "version": "2027.0.0-alpha-6", + "wpilibYear": "2027_alpha5", + "uuid": "3f48eb8c-50fe-43a6-9cb7-44c86353c4cb", + "mavenUrls": [ + "https://maven.revrobotics.com/" + ], + "jsonUrl": "https://software-metadata.revrobotics.com/REVLib-2027.json", + "javaDependencies": [ + { + "groupId": "com.revrobotics.frc", + "artifactId": "REVLib-java", + "version": "2027.0.0-alpha-6" + } + ], + "jniDependencies": [ + { + "groupId": "com.revrobotics.frc", + "artifactId": "REVLib-driver", + "version": "2027.0.0-alpha-6", + "skipInvalidPlatforms": true, + "isJar": false, + "validPlatforms": [ + "windowsx86-64", + "linuxarm64", + "linuxx86-64", + "linuxsystemcore", + "osxuniversal" + ] + }, + { + "groupId": "com.revrobotics.frc", + "artifactId": "RevLibBackendDriver", + "version": "2027.0.0-alpha-6", + "skipInvalidPlatforms": true, + "isJar": false, + "validPlatforms": [ + "windowsx86-64", + "linuxarm64", + "linuxx86-64", + "linuxsystemcore", + "osxuniversal" + ] + }, + { + "groupId": "com.revrobotics.frc", + "artifactId": "RevLibWpiBackendDriver", + "version": "2027.0.0-alpha-6", + "skipInvalidPlatforms": true, + "isJar": false, + "validPlatforms": [ + "windowsx86-64", + "linuxarm64", + "linuxx86-64", + "linuxsystemcore", + "osxuniversal" + ] + } + ], + "cppDependencies": [ + { + "groupId": "com.revrobotics.frc", + "artifactId": "REVLib-cpp", + "version": "2027.0.0-alpha-6", + "libName": "REVLib", + "headerClassifier": "headers", + "sharedLibrary": false, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxarm64", + "linuxx86-64", + "linuxsystemcore", + "osxuniversal" + ] + }, + { + "groupId": "com.revrobotics.frc", + "artifactId": "REVLib-driver", + "version": "2027.0.0-alpha-6", + "libName": "REVLibDriver", + "headerClassifier": "headers", + "sharedLibrary": false, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxarm64", + "linuxx86-64", + "linuxsystemcore", + "osxuniversal" + ] + }, + { + "groupId": "com.revrobotics.frc", + "artifactId": "RevLibBackendDriver", + "version": "2027.0.0-alpha-6", + "libName": "BackendDriver", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxarm64", + "linuxx86-64", + "linuxsystemcore", + "osxuniversal" + ] + }, + { + "groupId": "com.revrobotics.frc", + "artifactId": "RevLibWpiBackendDriver", + "version": "2027.0.0-alpha-6", + "libName": "REVLibWpi", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxarm64", + "linuxx86-64", + "linuxsystemcore", + "osxuniversal" + ] + } + ] +} \ No newline at end of file diff --git a/vendordeps/WPILibNewCommands.json b/vendordeps/WPILibNewCommands.json deleted file mode 100644 index c54ae11f..00000000 --- a/vendordeps/WPILibNewCommands.json +++ /dev/null @@ -1,38 +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" - ] - } - ] -} diff --git a/vendordeps/photonlib.json b/vendordeps/photonlib.json index 529f17b5..cb947f85 100644 --- a/vendordeps/photonlib.json +++ b/vendordeps/photonlib.json @@ -1,71 +1,71 @@ { - "fileName": "photonlib.json", - "name": "photonlib", - "version": "v2026.3.2", - "uuid": "515fe07e-bfc6-11fa-b3de-0242ac130004", - "frcYear": "2026", - "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": "v2026.3.2", - "skipInvalidPlatforms": true, - "isJar": false, - "validPlatforms": [ - "windowsx86-64", - "linuxathena", - "linuxx86-64", - "osxuniversal" - ] - } - ], - "cppDependencies": [ - { - "groupId": "org.photonvision", - "artifactId": "photonlib-cpp", - "version": "v2026.3.2", - "libName": "photonlib", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxathena", - "linuxx86-64", - "osxuniversal" - ] - }, - { - "groupId": "org.photonvision", - "artifactId": "photontargeting-cpp", - "version": "v2026.3.2", - "libName": "photontargeting", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxathena", - "linuxx86-64", - "osxuniversal" - ] - } - ], - "javaDependencies": [ - { - "groupId": "org.photonvision", - "artifactId": "photonlib-java", - "version": "v2026.3.2" - }, - { - "groupId": "org.photonvision", - "artifactId": "photontargeting-java", - "version": "v2026.3.2" - } - ] -} + "fileName": "photonlib.json", + "name": "photonlib", + "version": "v2027.0.0-alpha-2", + "uuid": "515fe07e-bfc6-11fa-b3de-0242ac130004", + "wpilibYear": "2027_alpha5", + "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": "v2027.0.0-alpha-2", + "skipInvalidPlatforms": true, + "isJar": false, + "validPlatforms": [ + "windowsx86-64", + "linuxsystemcore", + "linuxx86-64", + "osxuniversal" + ] + } + ], + "cppDependencies": [ + { + "groupId": "org.photonvision", + "artifactId": "photonlib-cpp", + "version": "v2027.0.0-alpha-2", + "libName": "photonlib", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxsystemcore", + "linuxx86-64", + "osxuniversal" + ] + }, + { + "groupId": "org.photonvision", + "artifactId": "photontargeting-cpp", + "version": "v2027.0.0-alpha-2", + "libName": "photontargeting", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxsystemcore", + "linuxx86-64", + "osxuniversal" + ] + } + ], + "javaDependencies": [ + { + "groupId": "org.photonvision", + "artifactId": "photonlib-java", + "version": "v2027.0.0-alpha-2" + }, + { + "groupId": "org.photonvision", + "artifactId": "photontargeting-java", + "version": "v2027.0.0-alpha-2" + } + ] +} \ No newline at end of file From 1f55ebf4453af025c0f866057134040023502d10 Mon Sep 17 00:00:00 2001 From: Theta Back Date: Tue, 8 Sep 2026 10:24:29 -0400 Subject: [PATCH 02/20] (#1) added autopilot locally, tried running in sim --- build.gradle | 1 - simgui-ds.json | 56 +++++ .../therekrab/autopilot/APConstraints.java | 122 ++++++++++ .../com/therekrab/autopilot/APProfile.java | 109 +++++++++ .../com/therekrab/autopilot/APTarget.java | 135 +++++++++++ .../com/therekrab/autopilot/Autopilot.java | 217 ++++++++++++++++++ 6 files changed, 639 insertions(+), 1 deletion(-) create mode 100644 simgui-ds.json create mode 100644 src/main/java/com/therekrab/autopilot/APConstraints.java create mode 100644 src/main/java/com/therekrab/autopilot/APProfile.java create mode 100644 src/main/java/com/therekrab/autopilot/APTarget.java create mode 100644 src/main/java/com/therekrab/autopilot/Autopilot.java diff --git a/build.gradle b/build.gradle index 1e9f37df..364b6ed6 100644 --- a/build.gradle +++ b/build.gradle @@ -102,7 +102,6 @@ dependencies { implementation "io.github.team401.coppercore:vision:$coppercoreVersion" implementation "io.github.team401.coppercore:wpilib_interface:$coppercoreVersion" implementation "io.github.team401.coppercore:metadata:$coppercoreVersion" - implementation "com.github.therekrab:autopilot:1.7.0-alpha-7" } test { diff --git a/simgui-ds.json b/simgui-ds.json new file mode 100644 index 00000000..cb2b8b0c --- /dev/null +++ b/simgui-ds.json @@ -0,0 +1,56 @@ +{"keyboardJoysticks": [{ + "axisConfig": [{ + "decKey": 546, + "incKey": 549 + }, { + "decKey": 568, + "incKey": 564 + }, { + "decKey": 550, + "decayRate": 0, + "incKey": 563, + "keyRate": 0.01 + }], + "axisCount": 3, + "buttonCount": 4, + "buttonKeys": [571, 569, 548, 567], + "povConfig": [{ + "keyDown": 614, + "keyDownLeft": 613, + "keyDownRight": 615, + "keyLeft": 616, + "keyRight": 618, + "keyUp": 620, + "keyUpLeft": 619, + "keyUpRight": 621 + }], + "povCount": 1 + }, { + "axisConfig": [{ + "decKey": 555, + "incKey": 557 + }, { + "decKey": 554, + "incKey": 556 + }], + "axisCount": 2, + "buttonCount": 4, + "buttonKeys": [558, 597, 599, 600], + "povCount": 0 + }, { + "axisConfig": [{ + "decKey": 513, + "incKey": 514 + }, { + "decKey": 515, + "incKey": 516 + }], + "axisCount": 2, + "buttonCount": 6, + "buttonKeys": [521, 519, 517, 522, 520, 518], + "povCount": 0 + }, { + "axisCount": 0, + "buttonCount": 0, + "povCount": 0 + }]} diff --git a/src/main/java/com/therekrab/autopilot/APConstraints.java b/src/main/java/com/therekrab/autopilot/APConstraints.java new file mode 100644 index 00000000..48a4d23b --- /dev/null +++ b/src/main/java/com/therekrab/autopilot/APConstraints.java @@ -0,0 +1,122 @@ +package com.therekrab.autopilot; + +/** + * A class that holds constraint information for an Autopilot action. + * + * Constraints are max velocity, acceleration, and jerk. + */ +public class APConstraints { + protected double velocity; + protected double acceleration; + protected double jerk; + + // These values represent the "cutoff" parameters that Autopilot uses to determine what should be + // happening during the end behavior of a path. These are always the same for a constant + // constraint, so to save the most computational time, they're precomputed with the constraint, + // rather than each time Autopilot.calculate is called. + + /** Cutoff distance */ + protected final double x0; + /** Velocity at cutoff distance */ + protected final double v0; + + /** + * Creates a blank APConstraints object. + *

+ * A blank APConstraints will not limit velocity, acceleration, or jerk. + */ + public APConstraints() { + this(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); + } + + /** + * Creates a new APConstraints object with a given max velocity, acceleration, and jerk. + * + * @param velocity The maximum velocity that Autopilot will demand, in m/s + * @param acceleration The maximum acceleration that Autopilot action will use to correct initial + * velocities, in m/s^2 + * @param jerk The maximum jerk that Autopilot will use to decelerate at the end of an action, in + * m/s^3 + */ + + public APConstraints(double velocity, double acceleration, double jerk) { + this.velocity = velocity; + this.acceleration = acceleration; + this.jerk = jerk; + + x0 = Math.pow(acceleration, 3.0) / (18.0 * jerk * jerk); + v0 = jerkConstrainedVelocity(x0); + } + + /** + * Create a new APConstraints object with a given max acceleration and jerk. + *

+ * This constructor defaults the velocity to unlimited. + * + * @param acceleration The maximum acceleration that Autopilot action will use to correct initial + * velocities, in m/s^2 + * @param jerk The maximum jerk that Autopilot will use to decelerate at the end of an action, in + * m/s^3 + * + */ + public APConstraints(double acceleration, double jerk) { + this(Double.POSITIVE_INFINITY, acceleration, jerk); + } + + /** + * Copies this APConstraints object, changes the copy's max velocity, and returns the copy. This + * affects the maximum velocity that Autopilot can demand. + * + * @param newVelocity The maximum velocity that Autopilot will demand, in m/s + */ + public APConstraints withVelocity(double newVelocity) { + return new APConstraints(newVelocity, this.acceleration, this.jerk); + } + + /** + * Copies this APConstraint object, changes the copy's acceleration, and returns the copy. This + * affects the maximum acceleration that Autopilot will use to correct initial velocities. + * + *

+ * Autopilot's acceleration is used at the beginning and end of an action + * + * @param newAcceleration The maximum acceleration that Autopilot will use to start a path, in + * m/s^2 + */ + public APConstraints withAcceleration(double newAcceleration) { + return new APConstraints(this.velocity, newAcceleration, this.jerk); + } + + /** + * Copies this APConstraint object, changes the copy's max jerk, and returns the copy. Higher + * values mean a faster deceleration. + * + * Autopilot's jerk is used at the end of an action (not relevant to Autopilot's start behavior). + * + * @param newJerk The maximum jerk that Autopilot will use to decelerate at the end of an action, + * in m/s^3 + */ + public APConstraints withJerk(double newJerk) { + return new APConstraints(this.velocity, this.acceleration, newJerk); + } + + /** + * Determines the maximum velocity required to travel the given distance and end at 0 m/s. + * + * @param dist The distance to travel, in meters + */ + protected double calculateMaxVelocity(double dist) { + if (dist > x0) { + return accelerationConstrainedVelocity(dist); + } + return jerkConstrainedVelocity(dist); + } + + private double accelerationConstrainedVelocity(double dist) { + return Math.sqrt(v0 * v0 + 2.0 * acceleration * (dist - x0)); + } + + private double jerkConstrainedVelocity(double dist) { + return Math.pow((4.5 * Math.pow(dist, 2.0)) * jerk, 1.0 / 3.0); + } +} diff --git a/src/main/java/com/therekrab/autopilot/APProfile.java b/src/main/java/com/therekrab/autopilot/APProfile.java new file mode 100644 index 00000000..75f9d994 --- /dev/null +++ b/src/main/java/com/therekrab/autopilot/APProfile.java @@ -0,0 +1,109 @@ +package com.therekrab.autopilot; + +import static org.wpilib.units.Units.Meters; +import static org.wpilib.units.Units.Rotations; +import org.wpilib.units.measure.Angle; +import org.wpilib.units.measure.Distance; + +/** + * A class representing a profile that determines how Autopilot approaches a target. + * + * The constraints property of the profile limits the robot's behavior. + * + *

Acceptable error for the controller (both translational and rotational) are stored here. + * + *

The "beeline radius" determines the distance at which the robot drives directly at the target and + * no longer respects entry angle. This is helpful because if the robot overshoots by a small + * amount, that error should not cause the robot do completely circle back around. + */ +public class APProfile { + protected APConstraints constraints; + protected Distance errorXY; + protected Angle errorTheta; + protected Distance beelineRadius; + + /** + * Builds an APProfile with the given constraints. Tolerated error and beeline radius are all set + * to zero. + * + * @param constraints The motion constraints for this profile + */ + public APProfile(APConstraints constraints) { + this.constraints = constraints; + errorXY = Meters.of(0); + errorTheta = Rotations.of(0); + beelineRadius = Meters.of(0); + } + + /** + * Modifies this profile's tolerated error in the XY plane and returns itself + * + * @param errorXY The tolerated translation error for this profile + */ + public APProfile withErrorXY(Distance errorXY) { + this.errorXY = errorXY; + return this; + } + + /** + * Modifies this profile's tolerated angular error and returns itself + * + * @param errorTheta The tolerated angular error for this profile + */ + public APProfile withErrorTheta(Angle errorTheta) { + this.errorTheta = errorTheta; + return this; + } + + /** + * Modifies this profile's path generation constraints and returns itself + * + * @param constraints The Autopilot constraints to apply to this profile + */ + public APProfile withConstraints(APConstraints constraints) { + this.constraints = constraints; + return this; + } + + /** + * Modifies this profile's beeline radius and returns itself + * + *

The beeline radius is a distance where, under that range, entry angle is no longer respected. + * This prevents small overshoots from causing the robot to make a full arc and instead correct + * itself. + * + * @param beelineRadius The distance at which the robot will drive directly at the target + */ + public APProfile withBeelineRadius(Distance beelineRadius) { + this.beelineRadius = beelineRadius; + return this; + } + + /** + * Returns the tolerated translation error for this profile. + */ + public Distance getErrorXY() { + return errorXY; + } + + /** + * Returns the tolerated angular error for this profile. + */ + public Angle getErrorTheta() { + return errorTheta; + } + + /** + * Returns the path generation constraints for this profile. + */ + public APConstraints getConstraints() { + return constraints; + } + + /** + * Returns the beeline radius for this profile. + */ + public Distance getBeelineRadius() { + return beelineRadius; + } +} diff --git a/src/main/java/com/therekrab/autopilot/APTarget.java b/src/main/java/com/therekrab/autopilot/APTarget.java new file mode 100644 index 00000000..4ade064e --- /dev/null +++ b/src/main/java/com/therekrab/autopilot/APTarget.java @@ -0,0 +1,135 @@ +package com.therekrab.autopilot; + +import java.util.Optional; +import org.wpilib.math.geometry.Pose2d; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.units.measure.Distance; + +/** + * The APTarget class represents the goal end state of an Autopilot action. + * + * A target needs a reference Pose2d, but can optionally have a specified entry angle and rotation + * radius. + * + * A target may also specify an end velocity or end velocity. + */ +public class APTarget { + protected Pose2d m_reference; + protected Optional m_entryAngle; + protected double m_velocity; + protected Optional m_rotationRadius; + + /** + * Creates a new Autopilot target with the given target pose, no entry angle, and no end velocity. + * + * @param pose The reference pose for this target. + */ + public APTarget(Pose2d pose) { + m_reference = pose; + m_velocity = 0; + m_entryAngle = Optional.empty(); + m_rotationRadius = Optional.empty(); + } + + /** + * Returns a copy of this target with the given reference Pose2d. + * + * @param reference The reference Pose2d for this target. + */ + public APTarget withReference(Pose2d reference) { + APTarget target = this.clone(); + target.m_reference = reference; + return target; + } + + /** + * Returns a copy of this target with the given entry angle. + * + * @param entryAngle The entry angle for the new target. + */ + public APTarget withEntryAngle(Rotation2d entryAngle) { + APTarget target = this.clone(); + target.m_entryAngle = Optional.of(entryAngle); + return target; + } + + /** + * Returns a copy of this target with the given end velocity. Note that if the robot does not + * reach this velocity, no issues will be thrown. Autopilot will only try to reach this target, + * but it will not be affected by whether it does. + * + * @param velocity The desired end velocity when the robot approaches the target + */ + public APTarget withVelocity(double velocity) { + APTarget target = this.clone(); + target.m_velocity = velocity; + return target; + } + + /** + * Returns a copy of this target with the given rotation radius. + * + *

Rotation radius is the distance from the target pose that rotation goals are respected. + * + *

By default, rotation goals are always respected. Adjusting this radius prevents Autopilot from reorienting + * the robot until the robot is within the specified radius of the target. + * + * @param radius The rotation radius for the new target + */ + public APTarget withRotationRadius(Distance radius) { + APTarget copy = this.clone(); + copy.m_rotationRadius = Optional.of(radius); + return copy; + } + + /** + * Returns this target's reference Pose2d. + */ + public Pose2d getReference() { + return m_reference; + } + + /** + * Returns this target's desired entry angle. + */ + public Optional getEntryAngle() { + return m_entryAngle; + } + + /** + * Returns this target's end velocity. + */ + public double getVelocity() { + return m_velocity; + } + + /** + * Returns this target's rotation radius. + */ + public Optional getRotationRadius() { + return m_rotationRadius; + } + + /** + * Creates a copy of this APTarget. + */ + public APTarget clone() { + APTarget target = new APTarget(m_reference); + target.m_velocity = m_velocity; + target.m_entryAngle = m_entryAngle; + target.m_rotationRadius = m_rotationRadius; + return target; + } + + /** + * Retuns a copy of this target, without the entry angle set. + * + *

This is useful if trying to make two different targets with and without entry angle set. + */ + public APTarget withoutEntryAngle() { + APTarget target = new APTarget(m_reference); + target.m_velocity = m_velocity; + target.m_rotationRadius = m_rotationRadius; + return target; + } +} diff --git a/src/main/java/com/therekrab/autopilot/Autopilot.java b/src/main/java/com/therekrab/autopilot/Autopilot.java new file mode 100644 index 00000000..6a80446d --- /dev/null +++ b/src/main/java/com/therekrab/autopilot/Autopilot.java @@ -0,0 +1,217 @@ +package com.therekrab.autopilot; + +import static org.wpilib.units.Units.Meters; +import static org.wpilib.units.Units.MetersPerSecond; +import static org.wpilib.units.Units.Radians; +import org.wpilib.math.geometry.Pose2d; +import org.wpilib.math.geometry.Rotation2d; +import org.wpilib.math.geometry.Translation2d; +import org.wpilib.math.kinematics.ChassisVelocities; +import org.wpilib.units.measure.LinearVelocity; + +/** + * Autopilot is a class that tries to drive a target to a goal in 2-D space. + * + * Autopilot is a stateless algorithm; as such, it does not "think ahead" and cannot avoid + * obstacles. Any math that Autopilot needs is already worked out such that only a small amount of + * computation is necessary on the fly. Autopilot is designed to be used in a drivetrain's control + * loop, where the current state of the robot is passed in, and the next velocity is returned. + * + */ +public class Autopilot { + private APProfile profile; + + private final double dt = 0.020; + + /** + * Constructs an Autopilot from a given profile. This is the profile that the autopilot will use + * for all actions. + */ + public Autopilot(APProfile profile) { + this.profile = profile; + } + + /** + * Returns the next field relative velocity for the trajectory + * + * @param current The robot's current position. + * @param robotRelativeSpeeds The robot's current robot relative ChassisVelocities. + * @param target The target the robot should drive towards. + * + * @return an APResult containing the next velocity and target angle + */ + public APResult calculate(Pose2d current, ChassisVelocities robotRelativeSpeeds, APTarget target) { + Translation2d offset = toTargetCoordinateFrame( + target.m_reference.getTranslation().minus(current.getTranslation()), target); + + if (offset.equals(Translation2d.kZero)) { + return new APResult( + MetersPerSecond.zero(), + MetersPerSecond.zero(), + target.m_reference.getRotation()); + } + + Translation2d fieldRelativeSpeeds = new Translation2d( + robotRelativeSpeeds.vx, + robotRelativeSpeeds.vy).rotateBy(current.getRotation()); + + Translation2d initial = toTargetCoordinateFrame(fieldRelativeSpeeds, target); + double disp = offset.getNorm(); + if (target.m_entryAngle.isEmpty() || disp < profile.beelineRadius.in(Meters)) { + Translation2d towardsTarget = offset.div(disp); + Translation2d goal = + towardsTarget.times(profile.constraints.calculateMaxVelocity(disp) + target.m_velocity); + Translation2d out = correct(initial, goal); + Translation2d velo = toGlobalCoordinateFrame(out, target); + Rotation2d rot = getRotationTarget(current.getRotation(), target, disp); + return new APResult(MetersPerSecond.of(velo.getX()), MetersPerSecond.of(velo.getY()), rot); + } + Translation2d goal = calculateSwirlyVelocity(offset, target); + Translation2d out = correct(initial, goal); + Translation2d velo = toGlobalCoordinateFrame(out, target); + Rotation2d rot = getRotationTarget(current.getRotation(), target, disp); + return new APResult(MetersPerSecond.of(velo.getX()), MetersPerSecond.of(velo.getY()), rot); + } + + /** + * Turns any other coordinate frame into a coordinate frame with positive x meaning in the + * direction of the target's entry angle, if applicable (otherwise no change to angles). + */ + private Translation2d toTargetCoordinateFrame(Translation2d coords, APTarget target) { + Rotation2d entryAngle = target.m_entryAngle.orElse(Rotation2d.kZero); + return coords.rotateBy(entryAngle.unaryMinus()); + } + + /** + * Turns a translation from a target-relative coordinate frame to a global coordinate frame. + */ + private Translation2d toGlobalCoordinateFrame(Translation2d coords, APTarget target) { + Rotation2d entryAngle = target.m_entryAngle.orElse(Rotation2d.kZero); + return coords.rotateBy(entryAngle); + } + + /** + * Attempts to drive the initial translation to the goal translation using the parameters for + * acceleration given in the profile. + * + * @param initial The initial translation to drive from + * @param goal The goal translation to drive to + */ + private Translation2d correct(Translation2d initial, Translation2d goal) { + Rotation2d angleOffset = Rotation2d.kZero; + if (!goal.equals(Translation2d.kZero)) { + angleOffset = new Rotation2d(goal.getX(), goal.getY()); + } + Translation2d adjustedGoal = goal.rotateBy(angleOffset.unaryMinus()); + Translation2d adjustedInitial = initial.rotateBy(angleOffset.unaryMinus()); + double initialI = adjustedInitial.getX(); + double goalI = adjustedGoal.getX(); + // we cap the adjusted I because we'd rather adjust now than overshoot. + if (goalI > profile.constraints.velocity) { + goalI = profile.constraints.velocity; + } + double adjustedI = Math.min(goalI, + push(initialI, goalI, profile.constraints.acceleration)); + return new Translation2d(adjustedI, 0).rotateBy(angleOffset); + } + + /** + * Using the provided acceleration, "pushes" the start point towards the end point. + * + * This is used for ensuring that changes in velocity are withing the acceleration threshold. + */ + private double push(double start, double end, double accel) { + double maxChange = accel * dt; + if (Math.abs(start - end) < maxChange) { + return end; + } + if (start > end) { + return start - maxChange; + } + return start + maxChange; + } + + /** + * Uses the swirly method to calculate the correct velocities for the robot, respecting entry + * angles. + * + * @param offset The offset from the robot to the target, in the target's coordinate frame + * @param target The target that Autopilot is trying to reach + */ + private Translation2d calculateSwirlyVelocity(Translation2d offset, APTarget target) { + double disp = offset.getNorm(); + Rotation2d theta = new Rotation2d(offset.getX(), offset.getY()); + double rads = theta.getRadians(); + double dist = calculateSwirlyLength(rads, disp); + double vx = theta.getCos() - rads * theta.getSin(); + double vy = rads * theta.getCos() + theta.getSin(); + return new Translation2d(vx, vy) + .div(Math.hypot(vx, vy)) // normalize + .times(profile.constraints.calculateMaxVelocity(dist) + target.m_velocity); // and scale to + // new length + } + + /** + * Using a precomputed integral, returns the length of the path that the swirly method generates. + * + *

+ * More specifically, this calculates the arc length of the polar curve r=theta from the given + * angle to zero, then scales it to match the current state. + * + * @param theta The angle of the offset from the robot to the target, in radians + * @param radius The normalized offset from the robot to the target, in meters + */ + private double calculateSwirlyLength(double theta, double radius) { + if (theta == 0) { + return radius; + } + theta = Math.abs(theta); + double hypot = Math.hypot(theta, 1); + double u1 = radius * hypot; + double u2 = radius * Math.log(theta + hypot) / theta; + return 0.5 * (u1 + u2); + } + + /** + * Returns the target's rotation if the robot is within a specified rotation radius; otherwise, + * returns the current rotation of the robot. + * + * @param current The current rotation of the robot. + * @param target The APTarget that Autopilot is trying to reach. + * @param dist The distance from the robot to the target. + */ + private Rotation2d getRotationTarget(Rotation2d current, APTarget target, double dist) { + if (target.m_rotationRadius.isEmpty()) { + return target.m_reference.getRotation(); + } + double radius = target.m_rotationRadius.get().in(Meters); + if (radius > dist) { + return target.m_reference.getRotation(); + } else { + return current; + } + } + + /** + * Return whether the given pose is within the tolerance of the APTarget. + * + * @param current The current pose of the robot. + * @param target The APTarget to check against. + * + * @return Returns true if Autopilot has reached the target. + */ + public boolean atTarget(Pose2d current, APTarget target) { + Pose2d goal = target.m_reference; + boolean okXY = Math.hypot(current.getX() - goal.getX(), + current.getY() - goal.getY()) <= profile.errorXY.in(Meters); + boolean okTheta = Math.abs(current.getRotation().minus(goal.getRotation()) + .getRadians()) <= profile.errorTheta.in(Radians); + return okXY && okTheta; + } + + /** + * The computed motion from a call to Autopilot.calculate(). + */ + public record APResult(LinearVelocity vx, LinearVelocity vy, Rotation2d targetAngle) { + } +} From e32938e7cc65afbcc2d3f96ca5ff68113f4186fc Mon Sep 17 00:00:00 2001 From: gback Date: Wed, 9 Sep 2026 22:40:14 -0400 Subject: [PATCH 03/20] (#1) fixed APConstraints JSON deserialization error Co-Authored-By: Codex 5.6 --- .../autopilot/APConstraintsTypeAdapter.java | 55 +++++++++++++++++++ .../java/frc/robot/autogen/GenerateAutos.java | 6 +- .../frc/robot/constants/JsonConstants.java | 3 + 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/therekrab/autopilot/APConstraintsTypeAdapter.java diff --git a/src/main/java/com/therekrab/autopilot/APConstraintsTypeAdapter.java b/src/main/java/com/therekrab/autopilot/APConstraintsTypeAdapter.java new file mode 100644 index 00000000..9eaa8783 --- /dev/null +++ b/src/main/java/com/therekrab/autopilot/APConstraintsTypeAdapter.java @@ -0,0 +1,55 @@ +package com.therekrab.autopilot; + +import com.google.gson.JsonParseException; +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; + +/** Gson adapter that reconstructs {@link APConstraints} and its derived final fields. */ +public final class APConstraintsTypeAdapter extends TypeAdapter { + @Override + public void write(JsonWriter out, APConstraints constraints) throws IOException { + if (constraints == null) { + out.nullValue(); + return; + } + + out.beginObject(); + out.name("velocity").value(constraints.velocity); + out.name("acceleration").value(constraints.acceleration); + out.name("jerk").value(constraints.jerk); + out.endObject(); + } + + @Override + public APConstraints read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + + Double velocity = null; + Double acceleration = null; + Double jerk = null; + + in.beginObject(); + while (in.hasNext()) { + switch (in.nextName()) { + case "velocity" -> velocity = in.nextDouble(); + case "acceleration" -> acceleration = in.nextDouble(); + case "jerk" -> jerk = in.nextDouble(); + default -> in.skipValue(); + } + } + in.endObject(); + + if (velocity == null || acceleration == null || jerk == null) { + throw new JsonParseException( + "APConstraints requires velocity, acceleration, and jerk fields"); + } + + return new APConstraints(velocity, acceleration, jerk); + } +} diff --git a/src/main/java/frc/robot/autogen/GenerateAutos.java b/src/main/java/frc/robot/autogen/GenerateAutos.java index ade6401f..37d0378d 100644 --- a/src/main/java/frc/robot/autogen/GenerateAutos.java +++ b/src/main/java/frc/robot/autogen/GenerateAutos.java @@ -22,6 +22,7 @@ import static frc.robot.autogen.Dsl.waitSeconds; import com.therekrab.autopilot.APConstraints; +import com.therekrab.autopilot.APConstraintsTypeAdapter; import com.therekrab.autopilot.APTarget; import coppercore.parameter_tools.json.JSONSync; import coppercore.parameter_tools.json.JSONSyncConfig; @@ -75,7 +76,10 @@ public static void main(String[] args) throws java.io.IOException { Autos autos = build(); JSONConverter.addConversion(APTarget.class, JSONAPTarget.class); - JSONSyncConfig config = new JSONSyncConfigBuilder().build(); + JSONSyncConfig config = + new JSONSyncConfigBuilder() + .addJsonTypeAdapter(APConstraints.class, new APConstraintsTypeAdapter()) + .build(); JSONSync sync = new JSONSync<>(autos, "", config); String json = sync.serialize(); diff --git a/src/main/java/frc/robot/constants/JsonConstants.java b/src/main/java/frc/robot/constants/JsonConstants.java index 8eaa5aa5..ca3c67fd 100644 --- a/src/main/java/frc/robot/constants/JsonConstants.java +++ b/src/main/java/frc/robot/constants/JsonConstants.java @@ -5,6 +5,8 @@ import static org.wpilib.units.Units.RotationsPerSecondPerSecond; import static org.wpilib.units.Units.Second; +import com.therekrab.autopilot.APConstraints; +import com.therekrab.autopilot.APConstraintsTypeAdapter; import com.therekrab.autopilot.APTarget; import coppercore.parameter_tools.json.JSONHandler; import coppercore.parameter_tools.json.JSONSyncConfigBuilder; @@ -74,6 +76,7 @@ public static JSONHandler loadConstants() { Controllers.applyControllerConfigToBuilder(jsonSyncSettings); + jsonSyncSettings.addJsonTypeAdapter(APConstraints.class, new APConstraintsTypeAdapter()); jsonSyncSettings.addJsonTypeAdapterFactory(new OptionalTypeAdapterFactory()); var pathProvider = environmentHandler.getEnvironmentPathProvider(); From edbcfa2fb96ce9c84ede76aea269de492ab7287c Mon Sep 17 00:00:00 2001 From: Theta Back Date: Sun, 13 Sep 2026 15:41:30 -0400 Subject: [PATCH 04/20] (#1) removed extra stddevs in flywheelsim --- src/main/java/frc/robot/constants/HopperConstants.java | 1 - src/main/java/frc/robot/constants/IndexerConstants.java | 1 - src/main/java/frc/robot/constants/ShooterConstants.java | 3 ++- src/main/java/frc/robot/constants/TransferRollerConstants.java | 1 - src/main/java/frc/robot/constants/TurretConstants.java | 3 +-- 5 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/frc/robot/constants/HopperConstants.java b/src/main/java/frc/robot/constants/HopperConstants.java index e79f1d08..75a781a8 100644 --- a/src/main/java/frc/robot/constants/HopperConstants.java +++ b/src/main/java/frc/robot/constants/HopperConstants.java @@ -107,7 +107,6 @@ public CoppercoreSimAdapter buildHopperSim() { simHopperMOI.in(KilogramSquareMeters), 1 / hopperReduction), DCMotor.getKrakenX60(1), - hopperReduction, 0.0)); } } diff --git a/src/main/java/frc/robot/constants/IndexerConstants.java b/src/main/java/frc/robot/constants/IndexerConstants.java index 346af71b..16765494 100644 --- a/src/main/java/frc/robot/constants/IndexerConstants.java +++ b/src/main/java/frc/robot/constants/IndexerConstants.java @@ -95,7 +95,6 @@ public CoppercoreSimAdapter buildIndexerSim() { simIndexerMOI.in(KilogramSquareMeters), 1 / indexerReduction), DCMotor.getKrakenX44Foc(1), - 0.0, 0.0)); } } diff --git a/src/main/java/frc/robot/constants/ShooterConstants.java b/src/main/java/frc/robot/constants/ShooterConstants.java index a0d952aa..37be14a0 100644 --- a/src/main/java/frc/robot/constants/ShooterConstants.java +++ b/src/main/java/frc/robot/constants/ShooterConstants.java @@ -214,6 +214,7 @@ public CoppercoreSimAdapter buildShooterSim() { new FlywheelSim( Models.flywheelFromPhysicalConstants( DCMotor.getKrakenX60Foc(3), shooterMOI.in(KilogramSquareMeters), 1.0), - DCMotor.getKrakenX60Foc(3))); + DCMotor.getKrakenX60Foc(3), + 0.0)); } } diff --git a/src/main/java/frc/robot/constants/TransferRollerConstants.java b/src/main/java/frc/robot/constants/TransferRollerConstants.java index e8f1c1c7..e3dc503e 100644 --- a/src/main/java/frc/robot/constants/TransferRollerConstants.java +++ b/src/main/java/frc/robot/constants/TransferRollerConstants.java @@ -93,7 +93,6 @@ public CoppercoreSimAdapter buildTransferRollerSim() { simTransferRollerMOI.in(KilogramSquareMeters), 1 / transferRollerReduction), DCMotor.getKrakenX44Foc(1), - 0.0, 0.0)); } } diff --git a/src/main/java/frc/robot/constants/TurretConstants.java b/src/main/java/frc/robot/constants/TurretConstants.java index e8a82fc2..0bde0464 100644 --- a/src/main/java/frc/robot/constants/TurretConstants.java +++ b/src/main/java/frc/robot/constants/TurretConstants.java @@ -168,8 +168,7 @@ public CoppercoreSimAdapter buildTurretSim() { simTurretMOI.in(KilogramSquareMeters), 1 / turretReduction), DCMotor.getKrakenX44Foc(1), - 0.0, - 0.0), + 0.0, 0.0), minTurretAngle, maxTurretAngle); } From 86d84b295fde51088b377ee87ed501b792962fac Mon Sep 17 00:00:00 2001 From: Theta Back Date: Wed, 16 Sep 2026 13:33:15 -0400 Subject: [PATCH 05/20] (#1) commented out Elastic alert to run in sim --- simgui-ds.json | 107 +++++++++--------- .../java/frc/robot/CoordinationLayer.java | 38 +++---- 2 files changed, 74 insertions(+), 71 deletions(-) diff --git a/simgui-ds.json b/simgui-ds.json index cb2b8b0c..ac74e387 100644 --- a/simgui-ds.json +++ b/simgui-ds.json @@ -1,56 +1,59 @@ -{"keyboardJoysticks": [{ - "axisConfig": [{ - "decKey": 546, - "incKey": 549 +{ + "keyboardJoysticks": [{ + "axisConfig": [{ + "decKey": 546, + "incKey": 549 + }, { + "decKey": 568, + "incKey": 564 + }, { + "decKey": 550, + "decayRate": 0, + "incKey": 563, + "keyRate": 0.01 + }], + "axisCount": 3, + "buttonCount": 4, + "buttonKeys": [571, 569, 548, 567], + "povConfig": [{ + "keyDown": 614, + "keyDownLeft": 613, + "keyDownRight": 615, + "keyLeft": 616, + "keyRight": 618, + "keyUp": 620, + "keyUpLeft": 619, + "keyUpRight": 621 + }], + "povCount": 1 }, { - "decKey": 568, - "incKey": 564 + "axisConfig": [{ + "decKey": 555, + "incKey": 557 + }, { + "decKey": 554, + "incKey": 556 + }], + "axisCount": 2, + "buttonCount": 4, + "buttonKeys": [558, 597, 599, 600], + "povCount": 0 }, { - "decKey": 550, - "decayRate": 0, - "incKey": 563, - "keyRate": 0.01 - }], - "axisCount": 3, - "buttonCount": 4, - "buttonKeys": [571, 569, 548, 567], - "povConfig": [{ - "keyDown": 614, - "keyDownLeft": 613, - "keyDownRight": 615, - "keyLeft": 616, - "keyRight": 618, - "keyUp": 620, - "keyUpLeft": 619, - "keyUpRight": 621 - }], - "povCount": 1 - }, { - "axisConfig": [{ - "decKey": 555, - "incKey": 557 - }, { - "decKey": 554, - "incKey": 556 - }], - "axisCount": 2, - "buttonCount": 4, - "buttonKeys": [558, 597, 599, 600], - "povCount": 0 - }, { - "axisConfig": [{ - "decKey": 513, - "incKey": 514 + "axisConfig": [{ + "decKey": 513, + "incKey": 514 + }, { + "decKey": 515, + "incKey": 516 + }], + "axisCount": 2, + "buttonCount": 6, + "buttonKeys": [521, 519, 517, 522, 520, 518], + "povCount": 0 }, { - "decKey": 515, - "incKey": 516 + "axisCount": 0, + "buttonCount": 0, + "povCount": 0 }], - "axisCount": 2, - "buttonCount": 6, - "buttonKeys": [521, 519, 517, 522, 520, 518], - "povCount": 0 - }, { - "axisCount": 0, - "buttonCount": 0, - "povCount": 0 - }]} + "robotJoysticks": [{"guid": "Keyboard0"}] + } diff --git a/src/main/java/frc/robot/CoordinationLayer.java b/src/main/java/frc/robot/CoordinationLayer.java index 855be4a4..4134018f 100644 --- a/src/main/java/frc/robot/CoordinationLayer.java +++ b/src/main/java/frc/robot/CoordinationLayer.java @@ -863,25 +863,25 @@ public void coordinateRobotActions() { autonomyOverriddenAlert.set(effectiveAutonomyLevel != autonomyLevel); - if (DriverStationBackend.isDisabled()) { - boolean lowVoltage = - JsonConstants.robotInfo.batteryVoltageAlert.isBatteryBelowThreshold( - RobotController.getBatteryVoltage()); - lowBatteryAlert.set(lowVoltage); - lowBatteryAlertRateLimiter.increment(); - if (lowVoltage - && lowBatteryAlertRateLimiter.consumeTokens(TOKENS_PER_ALERT) - && !(DriverStationBackend.isFMSAttached())) { - Elastic.sendNotification( - new Elastic.Notification( - Elastic.NotificationLevel.WARNING, - "Low Battery Voltage", - "Battery Voltage is below threshold.")); - } - } else { - // This alert is only for disabled mode. - lowBatteryAlert.set(false); - } + // if (DriverStationBackend.isDisabled()) { + // boolean lowVoltage = + // JsonConstants.robotInfo.batteryVoltageAlert.isBatteryBelowThreshold( + // RobotController.getBatteryVoltage()); + // lowBatteryAlert.set(lowVoltage); + // lowBatteryAlertRateLimiter.increment(); + // if (lowVoltage + // && lowBatteryAlertRateLimiter.consumeTokens(TOKENS_PER_ALERT) + // && !(DriverStationBackend.isFMSAttached())) { + // Elastic.sendNotification( + // new Elastic.Notification( + // Elastic.NotificationLevel.WARNING, + // "Low Battery Voltage", + // "Battery Voltage is below threshold.")); + // } + // } else { + // // This alert is only for disabled mode. + // lowBatteryAlert.set(false); + // } // Test whether we can shoot BEFORE running the shot calculator so that we can shoot for the // shot we were looking ahead to last cycle. From a0874dadd089d024b06114b9027d62f99a92b2da Mon Sep 17 00:00:00 2001 From: Godmar Back Date: Wed, 16 Sep 2026 16:00:06 -0400 Subject: [PATCH 06/20] enable gradle annotation processing (This allows successful start of the simulator) --- .vscode/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 6ea00dae..aef013c7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -28,7 +28,7 @@ "java.test.defaultConfig": "WPIlibUnitTests", "spotlessGradle.format.enable": true, "spotlessGradle.diagnostics.enable": false, - "java.import.gradle.annotationProcessing.enabled": false, + "java.import.gradle.annotationProcessing.enabled": true, "java.completion.favoriteStaticMembers": [ "org.junit.Assert.*", "org.junit.Assume.*", From 688949eff00b76b52671fc3bd0fbf5290a17cb39 Mon Sep 17 00:00:00 2001 From: Godmar Back Date: Wed, 16 Sep 2026 16:31:03 -0400 Subject: [PATCH 07/20] added gradlew build task before launching sim also put Elastic changes back in. --- .vscode/launch.json | 2 + .vscode/settings.json | 2 +- .vscode/tasks.json | 20 ++++++++++ .../java/frc/robot/CoordinationLayer.java | 38 +++++++++---------- 4 files changed, 42 insertions(+), 20 deletions(-) create mode 100644 .vscode/tasks.json diff --git a/.vscode/launch.json b/.vscode/launch.json index c9c9713d..d858cc26 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,12 +10,14 @@ "name": "WPILib Desktop Debug", "request": "launch", "desktop": true, + "preLaunchTask": "Gradle Build", }, { "type": "wpilib", "name": "WPILib roboRIO Debug", "request": "launch", "desktop": false, + "preLaunchTask": "Gradle Build", } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index aef013c7..6ea00dae 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -28,7 +28,7 @@ "java.test.defaultConfig": "WPIlibUnitTests", "spotlessGradle.format.enable": true, "spotlessGradle.diagnostics.enable": false, - "java.import.gradle.annotationProcessing.enabled": true, + "java.import.gradle.annotationProcessing.enabled": false, "java.completion.favoriteStaticMembers": [ "org.junit.Assert.*", "org.junit.Assume.*", diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..c65e3f75 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,20 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Gradle Build", + "type": "shell", + "command": "./gradlew", + "args": ["build"], + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "reveal": "always", + "panel": "shared" + }, + "problemMatcher": [] + } + ] +} diff --git a/src/main/java/frc/robot/CoordinationLayer.java b/src/main/java/frc/robot/CoordinationLayer.java index 4134018f..855be4a4 100644 --- a/src/main/java/frc/robot/CoordinationLayer.java +++ b/src/main/java/frc/robot/CoordinationLayer.java @@ -863,25 +863,25 @@ public void coordinateRobotActions() { autonomyOverriddenAlert.set(effectiveAutonomyLevel != autonomyLevel); - // if (DriverStationBackend.isDisabled()) { - // boolean lowVoltage = - // JsonConstants.robotInfo.batteryVoltageAlert.isBatteryBelowThreshold( - // RobotController.getBatteryVoltage()); - // lowBatteryAlert.set(lowVoltage); - // lowBatteryAlertRateLimiter.increment(); - // if (lowVoltage - // && lowBatteryAlertRateLimiter.consumeTokens(TOKENS_PER_ALERT) - // && !(DriverStationBackend.isFMSAttached())) { - // Elastic.sendNotification( - // new Elastic.Notification( - // Elastic.NotificationLevel.WARNING, - // "Low Battery Voltage", - // "Battery Voltage is below threshold.")); - // } - // } else { - // // This alert is only for disabled mode. - // lowBatteryAlert.set(false); - // } + if (DriverStationBackend.isDisabled()) { + boolean lowVoltage = + JsonConstants.robotInfo.batteryVoltageAlert.isBatteryBelowThreshold( + RobotController.getBatteryVoltage()); + lowBatteryAlert.set(lowVoltage); + lowBatteryAlertRateLimiter.increment(); + if (lowVoltage + && lowBatteryAlertRateLimiter.consumeTokens(TOKENS_PER_ALERT) + && !(DriverStationBackend.isFMSAttached())) { + Elastic.sendNotification( + new Elastic.Notification( + Elastic.NotificationLevel.WARNING, + "Low Battery Voltage", + "Battery Voltage is below threshold.")); + } + } else { + // This alert is only for disabled mode. + lowBatteryAlert.set(false); + } // Test whether we can shoot BEFORE running the shot calculator so that we can shoot for the // shot we were looking ahead to last cycle. From 3115ea67e0b88f50d1bdc20e107dc19c6d605ece Mon Sep 17 00:00:00 2001 From: Theta Back Date: Wed, 16 Sep 2026 19:21:30 -0400 Subject: [PATCH 08/20] (#1) commented out battery alert again --- .../java/frc/robot/CoordinationLayer.java | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/main/java/frc/robot/CoordinationLayer.java b/src/main/java/frc/robot/CoordinationLayer.java index 855be4a4..4134018f 100644 --- a/src/main/java/frc/robot/CoordinationLayer.java +++ b/src/main/java/frc/robot/CoordinationLayer.java @@ -863,25 +863,25 @@ public void coordinateRobotActions() { autonomyOverriddenAlert.set(effectiveAutonomyLevel != autonomyLevel); - if (DriverStationBackend.isDisabled()) { - boolean lowVoltage = - JsonConstants.robotInfo.batteryVoltageAlert.isBatteryBelowThreshold( - RobotController.getBatteryVoltage()); - lowBatteryAlert.set(lowVoltage); - lowBatteryAlertRateLimiter.increment(); - if (lowVoltage - && lowBatteryAlertRateLimiter.consumeTokens(TOKENS_PER_ALERT) - && !(DriverStationBackend.isFMSAttached())) { - Elastic.sendNotification( - new Elastic.Notification( - Elastic.NotificationLevel.WARNING, - "Low Battery Voltage", - "Battery Voltage is below threshold.")); - } - } else { - // This alert is only for disabled mode. - lowBatteryAlert.set(false); - } + // if (DriverStationBackend.isDisabled()) { + // boolean lowVoltage = + // JsonConstants.robotInfo.batteryVoltageAlert.isBatteryBelowThreshold( + // RobotController.getBatteryVoltage()); + // lowBatteryAlert.set(lowVoltage); + // lowBatteryAlertRateLimiter.increment(); + // if (lowVoltage + // && lowBatteryAlertRateLimiter.consumeTokens(TOKENS_PER_ALERT) + // && !(DriverStationBackend.isFMSAttached())) { + // Elastic.sendNotification( + // new Elastic.Notification( + // Elastic.NotificationLevel.WARNING, + // "Low Battery Voltage", + // "Battery Voltage is below threshold.")); + // } + // } else { + // // This alert is only for disabled mode. + // lowBatteryAlert.set(false); + // } // Test whether we can shoot BEFORE running the shot calculator so that we can shoot for the // shot we were looking ahead to last cycle. From b0b61cb3b331328fc2ca5e151c2c6cd542c9dcac Mon Sep 17 00:00:00 2001 From: Samson560915 Date: Wed, 16 Sep 2026 19:30:58 -0400 Subject: [PATCH 09/20] Created branch and sort of "changed" the normalizeHeading function to work on the angle in controlToTurretCentricPositionRaw rather than using the deprecated normalizeHeading function. --- .../subsystems/turret/TurretSubsystem.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java b/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java index 1cb41e6c..c6c101b2 100644 --- a/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java +++ b/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java @@ -473,8 +473,15 @@ private void controlToTurretCentricPosition(Angle goalAngleTurretCentric) { } private void controlToTurretCentricPositionRaw(Angle goalAngleTurretCentric) { - Logger.recordOutput("Turret/GoalAngle", goalAngleTurretCentric); + Logger.recordOutput("Turret/GoalAngle", goalAngleTurretCentric); //TODO: figure out where this is logged Angle clampedGoalAngle; + // With changes to normalize heading + // if goalAngelTurretCentric is negative, set it to 360 + goalAngleTurretCentric Degrees + + if (goalAngleTurretCentric.lt(Degrees.of(0))) { + goalAngleTurretCentric = Degrees.of(360).plus(goalAngleTurretCentric); + } + /* * Clamp the angle by: * - If it is within 0 to max turret angle, return it @@ -482,6 +489,7 @@ private void controlToTurretCentricPositionRaw(Angle goalAngleTurretCentric) { * - If it's greater than max angle but it's closer to max angle than to 360, return max angle * - If it's greater than max angle and is closer to 360 than to max angle, return 0 (same as 360) * */ + if (goalAngleTurretCentric.lt(JsonConstants.turretConstants.turretDiscontinuityMidpoint)) { clampedGoalAngle = UnitUtils.clampMeasure( @@ -509,13 +517,12 @@ private void controlToTurretCentricPositionRaw(Angle goalAngleTurretCentric) { */ protected void controlToGoalHeading() { Rotation2d robotRelativeHeading = goalTurretHeading.minus(dependencies.robotHeading); - // Rotation2d turretRelativeHeading = - // AngleUtil.normalizeHeading( - // robotRelativeHeading.plus( - // new Rotation2d(JsonConstants.turretConstants.headingToTurretAngle))); + Rotation2d turretRelativeHeading = + robotRelativeHeading.plus( + new Rotation2d(JsonConstants.turretConstants.headingToTurretAngle)); - // Angle adjustedGoalAngle = applyGoalAngleOffset(turretRelativeHeading.getMeasure()); - // controlToTurretCentricPositionRaw(adjustedGoalAngle); + Angle adjustedGoalAngle = applyGoalAngleOffset(turretRelativeHeading.getMeasure()); + controlToTurretCentricPositionRaw(adjustedGoalAngle); } private Angle getGoalAngleOffset(Angle goalAngleTurretCentric) { From c61b523f37427a4e2a713d9743e2afe23696566e Mon Sep 17 00:00:00 2001 From: Theta Back Date: Wed, 7 Oct 2026 19:42:37 -0400 Subject: [PATCH 10/20] (#1) updated Elastic.java so battery alert works --- build.gradle | 12 ++++++ .../java/frc/robot/CoordinationLayer.java | 38 +++++++++---------- src/main/java/frc/robot/util/Elastic.java | 23 +++++++---- 3 files changed, 46 insertions(+), 27 deletions(-) diff --git a/build.gradle b/build.gradle index 364b6ed6..46331e25 100644 --- a/build.gradle +++ b/build.gradle @@ -6,6 +6,18 @@ plugins { id "com.diffplug.spotless" version "8.1.0" } +// Taken from https://github.com/Gold872/elastic_dashboard/issues/386 +// +// Workaround until GradleRIO includes annotation processor resources (e.g. META-INF/services) +// on the VS Code classpath. Without it, avaje-jsonb @Json types fail under Simulate Robot Code. +eclipse.classpath.file.whenMerged { cp -> + if (!cp.entries.any { it.kind == 'src' && it.path == 'build/classes/java/main' }) { + def res = new org.gradle.plugins.ide.eclipse.model.SourceFolder('build/classes/java/main', null) + res.includes = ['META-INF/**'] + cp.entries.add(res) + } +} + java { sourceCompatibility = JavaVersion.VERSION_25 targetCompatibility = JavaVersion.VERSION_25 diff --git a/src/main/java/frc/robot/CoordinationLayer.java b/src/main/java/frc/robot/CoordinationLayer.java index 4134018f..855be4a4 100644 --- a/src/main/java/frc/robot/CoordinationLayer.java +++ b/src/main/java/frc/robot/CoordinationLayer.java @@ -863,25 +863,25 @@ public void coordinateRobotActions() { autonomyOverriddenAlert.set(effectiveAutonomyLevel != autonomyLevel); - // if (DriverStationBackend.isDisabled()) { - // boolean lowVoltage = - // JsonConstants.robotInfo.batteryVoltageAlert.isBatteryBelowThreshold( - // RobotController.getBatteryVoltage()); - // lowBatteryAlert.set(lowVoltage); - // lowBatteryAlertRateLimiter.increment(); - // if (lowVoltage - // && lowBatteryAlertRateLimiter.consumeTokens(TOKENS_PER_ALERT) - // && !(DriverStationBackend.isFMSAttached())) { - // Elastic.sendNotification( - // new Elastic.Notification( - // Elastic.NotificationLevel.WARNING, - // "Low Battery Voltage", - // "Battery Voltage is below threshold.")); - // } - // } else { - // // This alert is only for disabled mode. - // lowBatteryAlert.set(false); - // } + if (DriverStationBackend.isDisabled()) { + boolean lowVoltage = + JsonConstants.robotInfo.batteryVoltageAlert.isBatteryBelowThreshold( + RobotController.getBatteryVoltage()); + lowBatteryAlert.set(lowVoltage); + lowBatteryAlertRateLimiter.increment(); + if (lowVoltage + && lowBatteryAlertRateLimiter.consumeTokens(TOKENS_PER_ALERT) + && !(DriverStationBackend.isFMSAttached())) { + Elastic.sendNotification( + new Elastic.Notification( + Elastic.NotificationLevel.WARNING, + "Low Battery Voltage", + "Battery Voltage is below threshold.")); + } + } else { + // This alert is only for disabled mode. + lowBatteryAlert.set(false); + } // Test whether we can shoot BEFORE running the shot calculator so that we can shoot for the // shot we were looking ahead to last cycle. diff --git a/src/main/java/frc/robot/util/Elastic.java b/src/main/java/frc/robot/util/Elastic.java index 102558eb..e07429c9 100644 --- a/src/main/java/frc/robot/util/Elastic.java +++ b/src/main/java/frc/robot/util/Elastic.java @@ -1,5 +1,5 @@ // This code is taken from -// https://github.com/Gold872/elastic_dashboard/blob/3673f6b4135cbc429bb1f43e6ab109378ab2de6d/elasticlib/Elastic.java +// https://github.com/Gold872/elastic_dashboard/blob/main/elasticlib/Elastic.java// // // Copyright (c) 2023-2026 Gold87 and other Elastic contributors // This software can be modified and/or shared under the terms @@ -8,6 +8,7 @@ package frc.robot.util; +import io.avaje.json.JsonException; import io.avaje.jsonb.Json; import io.avaje.jsonb.JsonType; import io.avaje.jsonb.Jsonb; @@ -20,13 +21,14 @@ public final class Elastic { private static final StringTopic notificationTopic = NetworkTableInstance.getDefault().getStringTopic("/Elastic/RobotNotifications"); private static final StringPublisher notificationPublisher = - notificationTopic.publish(new PubSubOption.SendAll(true), new PubSubOption.KeepDuplicates(true)); + notificationTopic.publish(PubSubOption.SEND_ALL, PubSubOption.KEEP_DUPLICATES); private static final StringTopic selectedTabTopic = NetworkTableInstance.getDefault().getStringTopic("/Elastic/SelectedTab"); private static final StringPublisher selectedTabPublisher = - selectedTabTopic.publish(new PubSubOption.KeepDuplicates(true)); - private static final Jsonb jsonb = Jsonb.builder().serializeNulls(true).build(); - private static final JsonType notificationJson = jsonb.type(Notification.class); + selectedTabTopic.publish(PubSubOption.KEEP_DUPLICATES); + private static final Jsonb jsonb = Jsonb.builder().build(); + private static final JsonType notificationJsonType = + jsonb.type(Notification.class); /** * Represents the possible levels of notifications for the Elastic dashboard. These levels are @@ -49,8 +51,8 @@ public enum NotificationLevel { */ public static void sendNotification(Notification notification) { try { - notificationPublisher.set(notificationJson.toJson(notification)); - } catch (RuntimeException e) { + notificationPublisher.set(notificationJsonType.toJson(notification)); + } catch (JsonException e) { e.printStackTrace(); } } @@ -85,17 +87,22 @@ public static void selectTab(int tabIndex) { */ @Json public static class Notification { + @Json.Property("level") private NotificationLevel level; + @Json.Property("title") private String title; + @Json.Property("description") private String description; @Json.Property("displayTime") private int displayTimeMillis; + @Json.Property("width") private double width; + @Json.Property("height") private double height; /** @@ -387,4 +394,4 @@ public Notification withNoAutoDismiss() { return this; } } -} +} \ No newline at end of file From 34c094e35c09885958bb9068f4954b4423a774a0 Mon Sep 17 00:00:00 2001 From: Samson560915 Date: Mon, 19 Oct 2026 18:36:15 -0400 Subject: [PATCH 11/20] Added change to allow you to see the goalTurretHeading of the turret in 2d advantagescope. --- .../java/frc/robot/CoordinationLayer.java | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/main/java/frc/robot/CoordinationLayer.java b/src/main/java/frc/robot/CoordinationLayer.java index 4134018f..284c74af 100644 --- a/src/main/java/frc/robot/CoordinationLayer.java +++ b/src/main/java/frc/robot/CoordinationLayer.java @@ -26,11 +26,13 @@ import org.wpilib.math.geometry.Pose3d; import org.wpilib.math.geometry.Rotation2d; import org.wpilib.math.geometry.Rotation3d; +import org.wpilib.math.geometry.Transform3d; import org.wpilib.math.geometry.Translation2d; import org.wpilib.math.geometry.Translation3d; import org.wpilib.math.kinematics.ChassisVelocities; import org.wpilib.math.numbers.N3; import org.wpilib.math.util.Units; +import org.wpilib.units.measure.Angle; import org.wpilib.units.measure.Time; import org.wpilib.driverstation.Alert; import org.wpilib.driverstation.internal.DriverStationBackend; @@ -1228,6 +1230,29 @@ private boolean shouldStowHoodBasedOnMovement(Drive drive, HoodSubsystem hood) { new Pose2d(movementEnd, robotPose.getRotation())); EnhancedLine2d movementLine = new EnhancedLine2d(movementStart, movementEnd); + Translation2d turretLocation = new Pose3d(robotPose) + .plus(JsonConstants.robotInfo.robotToShooter) + .getTranslation() + .toTranslation2d(); + + //Angle turretAngle = turret.map(TurretSubsystem::getTurretAngleRobotRelative).orElse(Radians.of(1)); + + + double turretAngle = turret.map(turret -> turret.getGoalTurretHeading().getRadians()).orElse(0.0); + + Rotation3d turretRotation = new Rotation3d(new Rotation2d(turretAngle)); + + Transform3d turretFuturePosition = new Transform3d(new Translation3d(3.0, turretRotation), new Rotation3d()); + + Translation2d turretDirection = new Pose3d(robotPose) + .plus(JsonConstants.robotInfo.robotToShooter.plus(turretFuturePosition)) + .getTranslation() + .toTranslation2d(); + + Logger.recordOutput( + "CoordinationLayer/TurretTrajectory", + new Translation2d[] {turretLocation, turretDirection}); + for (var trench : trenches) { if (movementLine.intersects(trench)) { return true; @@ -1370,7 +1395,7 @@ private boolean runShotCalculatorWithDrive(Drive driveInstance) { turret.ifPresent( turret -> { turret.targetGoalHeading(shot.yaw()); - }); + }); hood.ifPresent( hood -> { From 7c0342c2b12985c642ab8a1f3d02afe5d149233d Mon Sep 17 00:00:00 2001 From: Theta Back Date: Wed, 21 Oct 2026 21:01:52 -0400 Subject: [PATCH 12/20] (#1) updated to alpha 7 --- .vscode/launch.json | 4 +- .vscode/settings.json | 17 +-- .wpilib/wpilib_preferences.json | 2 +- build.gradle | 25 ++-- settings.gradle | 14 ++- simgui-ds.json | 115 +++++++++--------- .../com/therekrab/autopilot/Autopilot.java | 10 +- src/main/java/first/Main.java | 4 +- .../java/frc/robot/CoordinationLayer.java | 17 +-- src/main/java/frc/robot/InitSubsystems.java | 17 +-- src/main/java/frc/robot/Main.java | 29 ----- src/main/java/frc/robot/Robot.java | 81 ++++++------ src/main/java/frc/robot/RobotContainer.java | 34 +++--- src/main/java/frc/robot/ShotCalculations.java | 12 +- src/main/java/frc/robot/autogen/Field.java | 2 +- .../frc/robot/commands/DriveCommands.java | 6 +- .../robot/constants/AprilTagConstants.java | 19 +-- .../frc/robot/constants/JsonConstants.java | 2 + .../robot/constants/ManualModeConstants.java | 4 +- .../java/frc/robot/constants/RobotInfo.java | 4 +- .../java/frc/robot/constants/ShotMaps.java | 8 +- .../drive/PhysicalDriveConstants.java | 2 +- .../frc/robot/coordination/MatchState.java | 24 ++-- .../frc/robot/generated/TunerConstants.java | 4 +- .../subsystems/climber/ClimberState.java | 2 +- .../subsystems/climber/ClimberSubsystem.java | 2 +- .../frc/robot/subsystems/drive/Drive.java | 31 +++-- .../subsystems/drive/DriveCoordinator.java | 4 +- .../frc/robot/subsystems/drive/GyroIO.java | 2 +- .../frc/robot/subsystems/drive/Module.java | 8 +- .../frc/robot/subsystems/drive/ModuleIO.java | 4 +- .../subsystems/drive/ModuleIOTalonFX.java | 6 +- .../subsystems/drive/ModuleIOTalonFXS.java | 6 +- .../frc/robot/subsystems/hood/HoodState.java | 2 +- .../robot/subsystems/hood/HoodSubsystem.java | 4 +- .../robot/subsystems/hopper/HopperState.java | 2 +- .../subsystems/hopper/HopperSubsystem.java | 4 +- .../subsystems/indexer/IndexerState.java | 2 +- .../subsystems/indexer/IndexerSubsystem.java | 4 +- .../subsystems/shooter/ShooterState.java | 4 +- .../subsystems/shooter/ShooterSubsystem.java | 6 +- .../transferroller/TransferRollerState.java | 2 +- .../TransferRollerSubsystem.java | 4 +- .../robot/subsystems/turret/TurretState.java | 2 +- .../subsystems/turret/TurretSubsystem.java | 7 +- .../java/frc/robot/util/LocalADStarAK.java | 2 +- .../robot/util/littletonUtil/GeomUtil.java | 2 +- vendordeps/AdvantageKit.json | 11 +- vendordeps/AprilTag.json | 91 ++++++++++++++ vendordeps/CameraServer.json | 114 +++++++++++++++++ vendordeps/CommandsV2.json | 88 +++++++------- vendordeps/PathplannerLibSystemCoreAlpha.json | 8 +- ...a-1.json => Phoenix6-26.70.0-alpha-2.json} | 64 +++++----- vendordeps/REVLib.json | 20 +-- ...tonlib-v2027.0.0-alpha-2-86-gda55d785.json | 84 +++++++++++++ vendordeps/photonlib.json | 71 ----------- 56 files changed, 655 insertions(+), 464 deletions(-) delete mode 100644 src/main/java/frc/robot/Main.java create mode 100644 vendordeps/AprilTag.json create mode 100644 vendordeps/CameraServer.json rename vendordeps/{Phoenix6-26.50.0-alpha-1.json => Phoenix6-26.70.0-alpha-2.json} (90%) create mode 100644 vendordeps/photonlib-v2027.0.0-alpha-2-86-gda55d785.json delete mode 100644 vendordeps/photonlib.json diff --git a/.vscode/launch.json b/.vscode/launch.json index d858cc26..6d2cc2fc 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,14 +10,12 @@ "name": "WPILib Desktop Debug", "request": "launch", "desktop": true, - "preLaunchTask": "Gradle Build", }, { "type": "wpilib", - "name": "WPILib roboRIO Debug", + "name": "WPILib Systemcore Debug", "request": "launch", "desktop": false, - "preLaunchTask": "Gradle Build", } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 6ea00dae..f6cf31d5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -26,8 +26,6 @@ }, ], "java.test.defaultConfig": "WPIlibUnitTests", - "spotlessGradle.format.enable": true, - "spotlessGradle.diagnostics.enable": false, "java.import.gradle.annotationProcessing.enabled": false, "java.completion.favoriteStaticMembers": [ "org.junit.Assert.*", @@ -59,18 +57,7 @@ "org.wpilib.math.**.proto.*", "org.wpilib.math.**.struct.*", ], + "java.debug.settings.enableRunDebugCodeLens": false, "java.dependency.enableDependencyCheckup": false, - "editor.defaultFormatter": "richardwillis.vscode-spotless-gradle", - "[json]": { - "editor.defaultFormatter": "richardwillis.vscode-spotless-gradle" - }, - "[java]": { - "editor.defaultFormatter": "richardwillis.vscode-spotless-gradle" - }, - "java.compile.nullAnalysis.mode": "automatic", - "cSpell.words": [ - "Coppercore", - "Tunables" - ], - "java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx32G -Xms100m -Xlog:disable" + "java.compile.nullAnalysis.mode": "automatic" } diff --git a/.wpilib/wpilib_preferences.json b/.wpilib/wpilib_preferences.json index ad433eca..30f5d7d6 100644 --- a/.wpilib/wpilib_preferences.json +++ b/.wpilib/wpilib_preferences.json @@ -1,6 +1,6 @@ { "enableCppIntellisense": false, "currentLanguage": "java", - "projectYear": "2027_alpha5", + "projectYear": "2027_alpha7", "teamNumber": 401 } \ No newline at end of file diff --git a/build.gradle b/build.gradle index 46331e25..1d79a681 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ plugins { id "java" - id "org.wpilib.GradleRIO" version "2027.0.0-alpha-6" - id "com.gradleup.shadow" version "9.3.0" + id "application" + id "org.wpilib.GradleRIO" version "2027.0.0-alpha-7" id "com.peterabeles.gversion" version "1.10" id "com.diffplug.spotless" version "8.1.0" } @@ -50,6 +50,7 @@ deploy { // getTargetTypeClass is a shortcut to get the class type using a string wpilibJava(getArtifactTypeClass('WPILibJavaArtifact')) { + debugJni = false; } // Static files artifact @@ -68,7 +69,7 @@ def deployArtifact = deploy.targets.systemcore.artifacts.wpilibJava // Set to true to use debug for all targets including JNI, which will drastically impact // performance. -wpi.java.debugJni = false +wpi.java.runSimWithDebugJni = false // Set this to true to enable desktop support. def includeDesktopSupport = false @@ -100,7 +101,7 @@ dependencies { def akitJson = new groovy.json.JsonSlurper().parseText(new File(projectDir.getAbsolutePath() + "/vendordeps/AdvantageKit.json").text) annotationProcessor "org.littletonrobotics.akit:akit-autolog:$akitJson.version" - def coppercoreVersion = "2026.3.1" + def coppercoreVersion = "2026.3.4" implementation "com.google.code.gson:gson:2.11.0" implementation "io.avaje:avaje-jsonb:3.14" @@ -128,20 +129,18 @@ 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() +application.mainClass = ROBOT_MAIN_CLASS + +deployArtifact.configureApplication(application) +wpi.java.configureApplication(application) +wpi.java.configureTestTasks(test) + +jar { 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' diff --git a/settings.gradle b/settings.gradle index e2626a81..a17bda05 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,18 +2,26 @@ import org.gradle.internal.os.OperatingSystem pluginManagement { repositories { - String wpilibYear = '2027_alpha5' + String wpilibYear = '2027_alpha7' File wpilibHome - if (OperatingSystem.current().isWindows()) { + def os = OperatingSystem.current() + if (os.isWindows()) { String publicFolder = System.getenv('PUBLIC') if (publicFolder == null) { publicFolder = "C:\\Users\\Public" } def homeRoot = new File(publicFolder, "wpilib") wpilibHome = new File(homeRoot, wpilibYear) + } else if (os.isLinux()) { + String xdgDataHome = System.getenv('XDG_DATA_HOME') + if (xdgDataHome == null || xdgDataHome.trim().isEmpty() || !new File(xdgDataHome).isAbsolute()) { + xdgDataHome = new File(System.getProperty("user.home"), ".local/share").getPath() + } + def homeRoot = new File(xdgDataHome, "wpilib") + wpilibHome = new File(homeRoot, wpilibYear) } else { def userFolder = System.getProperty("user.home") - def homeRoot = new File(userFolder, "wpilib") + def homeRoot = new File(userFolder, ".wpilib") wpilibHome = new File(homeRoot, wpilibYear) } def wpilibHomeMaven = new File(wpilibHome, 'maven') diff --git a/simgui-ds.json b/simgui-ds.json index ac74e387..5096a581 100644 --- a/simgui-ds.json +++ b/simgui-ds.json @@ -1,59 +1,58 @@ { - "keyboardJoysticks": [{ - "axisConfig": [{ - "decKey": 546, - "incKey": 549 - }, { - "decKey": 568, - "incKey": 564 - }, { - "decKey": 550, - "decayRate": 0, - "incKey": 563, - "keyRate": 0.01 - }], - "axisCount": 3, - "buttonCount": 4, - "buttonKeys": [571, 569, 548, 567], - "povConfig": [{ - "keyDown": 614, - "keyDownLeft": 613, - "keyDownRight": 615, - "keyLeft": 616, - "keyRight": 618, - "keyUp": 620, - "keyUpLeft": 619, - "keyUpRight": 621 - }], - "povCount": 1 - }, { - "axisConfig": [{ - "decKey": 555, - "incKey": 557 - }, { - "decKey": 554, - "incKey": 556 - }], - "axisCount": 2, - "buttonCount": 4, - "buttonKeys": [558, 597, 599, 600], - "povCount": 0 - }, { - "axisConfig": [{ - "decKey": 513, - "incKey": 514 - }, { - "decKey": 515, - "incKey": 516 - }], - "axisCount": 2, - "buttonCount": 6, - "buttonKeys": [521, 519, 517, 522, 520, 518], - "povCount": 0 - }, { - "axisCount": 0, - "buttonCount": 0, - "povCount": 0 - }], - "robotJoysticks": [{"guid": "Keyboard0"}] - } + "Display": {"window": {"visible": false}}, + "Keyboard 0 Settings": {"window": {"visible": true}}, + "keyboardJoysticks": [{ + "axisConfig": [{ + "decKey": 546, + "incKey": 549 + }, { + "decKey": 568, + "incKey": 564 + }, { + "decKey": 550, + "decayRate": 0, + "incKey": 563, + "keyRate": 0.01 + }, {}, { + "decKey": 556, + "incKey": 555 + }], + "axisCount": 5, + "buttonCount": 4, + "buttonKeys": [571, 569, 548, 567], + "povConfig": [{ + "keyDown": 614, + "keyDownLeft": 613, + "keyDownRight": 615, + "keyLeft": 616, + "keyRight": 618, + "keyUp": 620, + "keyUpLeft": 619, + "keyUpRight": 621 + }], + "povCount": 1 + }, { + "axisConfig": [{"incKey": 557}, {"decKey": 554}], + "axisCount": 2, + "buttonCount": 4, + "buttonKeys": [558, 597, 599, 600], + "povCount": 0 + }, { + "axisConfig": [{ + "decKey": 513, + "incKey": 514 + }, { + "decKey": 515, + "incKey": 516 + }], + "axisCount": 2, + "buttonCount": 6, + "buttonKeys": [521, 519, 517, 522, 520, 518], + "povCount": 0 + }, { + "axisCount": 0, + "buttonCount": 0, + "povCount": 0 + }], + "robotJoysticks": [{"guid": "Keyboard0"}] +} diff --git a/src/main/java/com/therekrab/autopilot/Autopilot.java b/src/main/java/com/therekrab/autopilot/Autopilot.java index 6a80446d..ae59ed71 100644 --- a/src/main/java/com/therekrab/autopilot/Autopilot.java +++ b/src/main/java/com/therekrab/autopilot/Autopilot.java @@ -44,7 +44,7 @@ public APResult calculate(Pose2d current, ChassisVelocities robotRelativeSpeeds, Translation2d offset = toTargetCoordinateFrame( target.m_reference.getTranslation().minus(current.getTranslation()), target); - if (offset.equals(Translation2d.kZero)) { + if (offset.equals(Translation2d.ZERO)) { return new APResult( MetersPerSecond.zero(), MetersPerSecond.zero(), @@ -78,7 +78,7 @@ public APResult calculate(Pose2d current, ChassisVelocities robotRelativeSpeeds, * direction of the target's entry angle, if applicable (otherwise no change to angles). */ private Translation2d toTargetCoordinateFrame(Translation2d coords, APTarget target) { - Rotation2d entryAngle = target.m_entryAngle.orElse(Rotation2d.kZero); + Rotation2d entryAngle = target.m_entryAngle.orElse(Rotation2d.ZERO); return coords.rotateBy(entryAngle.unaryMinus()); } @@ -86,7 +86,7 @@ private Translation2d toTargetCoordinateFrame(Translation2d coords, APTarget tar * Turns a translation from a target-relative coordinate frame to a global coordinate frame. */ private Translation2d toGlobalCoordinateFrame(Translation2d coords, APTarget target) { - Rotation2d entryAngle = target.m_entryAngle.orElse(Rotation2d.kZero); + Rotation2d entryAngle = target.m_entryAngle.orElse(Rotation2d.ZERO); return coords.rotateBy(entryAngle); } @@ -98,8 +98,8 @@ private Translation2d toGlobalCoordinateFrame(Translation2d coords, APTarget tar * @param goal The goal translation to drive to */ private Translation2d correct(Translation2d initial, Translation2d goal) { - Rotation2d angleOffset = Rotation2d.kZero; - if (!goal.equals(Translation2d.kZero)) { + Rotation2d angleOffset = Rotation2d.ZERO; + if (!goal.equals(Translation2d.ZERO)) { angleOffset = new Rotation2d(goal.getX(), goal.getY()); } Translation2d adjustedGoal = goal.rotateBy(angleOffset.unaryMinus()); diff --git a/src/main/java/first/Main.java b/src/main/java/first/Main.java index 8fd1dabb..fe6e4fdc 100644 --- a/src/main/java/first/Main.java +++ b/src/main/java/first/Main.java @@ -6,6 +6,8 @@ import org.wpilib.framework.RobotBase; +import frc.robot.Robot; + /** * Do NOT add any static variables to this class, or any initialization at all. Unless you know what * you are doing, do not modify this file except to change the parameter class to the startRobot @@ -20,6 +22,6 @@ private Main() {} *

If you change your main robot class, change the parameter type. */ public static void main(String... args) { - RobotBase.startRobot(frc.robot.Robot.class); + RobotBase.startRobot(Robot::new); } } diff --git a/src/main/java/frc/robot/CoordinationLayer.java b/src/main/java/frc/robot/CoordinationLayer.java index 855be4a4..a31dd090 100644 --- a/src/main/java/frc/robot/CoordinationLayer.java +++ b/src/main/java/frc/robot/CoordinationLayer.java @@ -32,7 +32,7 @@ import org.wpilib.math.numbers.N3; import org.wpilib.math.util.Units; import org.wpilib.units.measure.Time; -import org.wpilib.driverstation.Alert; +import org.wpilib.util.Alert; import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.system.RobotController; import org.wpilib.event.EventLoop; @@ -117,7 +117,7 @@ public enum AutonomyLevel { private final Debouncer visionConnectedDebouncer = new Debouncer( JsonConstants.visionConstants.disconnectedDebounceTime.in(Seconds), - DebounceType.kFalling); + DebounceType.FALLING); /* Update connection debouncer time */ void setVisionConnectionDebouncerTime(Time debounceTime) { @@ -216,12 +216,15 @@ public enum PassGoalZone { new TestModeManager<>("CoordinationLayer", CoordinationTestMode.class); // Logging - private final Alert autonomyOverriddenAlert = + private static final Alert autonomyOverriddenAlert = new Alert( + "autonomy_level_forced_manual", "Autonomy level forced to manual due to disconnected coprocessor.", Alert.Level.MEDIUM); - private final Alert visionDisconnectedAlert = - new Alert("Coprocessor disconnected", Alert.Level.HIGH); - private final Alert lowBatteryAlert = new Alert("Battery voltage low", Alert.Level.MEDIUM); + private static final Alert visionDisconnectedAlert = + new Alert( + "disconnected_coprocessor", + "Coprocessor disconnected", Alert.Level.HIGH); + private static final Alert lowBatteryAlert = new Alert("low_battery", "Battery voltage low", Alert.Level.MEDIUM); // These constants will give a burst of two low battery voltage alerts, then one every second. private final TokenBucket lowBatteryAlertRateLimiter = new TokenBucket(200, 2); @@ -1117,7 +1120,7 @@ private void aimForTestModeShot(Drive driveInstance) { case PassRightNZ -> FieldLocations.rightNZPassingTarget(); }; - Rotation2d yaw = targetPose.minus(shooterPosition).getAngle(); + Rotation2d yaw = targetPose.minus(shooterPosition).getAngle().get(); Logger.recordOutput( "CoordinationLayer/distanceToTarget", diff --git a/src/main/java/frc/robot/InitSubsystems.java b/src/main/java/frc/robot/InitSubsystems.java index becd9e00..864e6fb6 100644 --- a/src/main/java/frc/robot/InitSubsystems.java +++ b/src/main/java/frc/robot/InitSubsystems.java @@ -1,7 +1,12 @@ package frc.robot; +import java.util.Optional; + +import org.wpilib.math.geometry.Transform3d; + import com.ctre.phoenix6.configs.TalonFXConfiguration; import com.ctre.phoenix6.sim.TalonFXSimState.MotorType; + import coppercore.vision.VisionIO; import coppercore.vision.VisionIOPhotonReal; import coppercore.vision.VisionIOPhotonSim; @@ -13,8 +18,7 @@ import coppercore.wpilib_interface.subsystems.motors.talonfx.MotorIOTalonFX; import coppercore.wpilib_interface.subsystems.motors.talonfx.MotorIOTalonFXSim; import coppercore.wpilib_interface.subsystems.sim.CoppercoreSimAdapter; -import org.wpilib.vision.apriltag.AprilTagFieldLayout; -import org.wpilib.math.geometry.Transform3d; +import org.wpilib.fields.Field; import frc.robot.constants.JsonConstants; import frc.robot.subsystems.climber.ClimberSubsystem; import frc.robot.subsystems.drive.Drive; @@ -34,7 +38,6 @@ import frc.robot.subsystems.shooter.ShooterSubsystem; import frc.robot.subsystems.transferroller.TransferRollerSubsystem; import frc.robot.subsystems.turret.TurretSubsystem; -import java.util.Optional; /** * The InitSubsystems class contains static methods to instantiate each subsystem. It is separated @@ -124,7 +127,7 @@ public static Drive initDriveSubsystem() { public static VisionLocalizer initVisionSubsystem(Drive drive) { var visionConstants = JsonConstants.visionConstants; var gainConstants = visionConstants.gainConstants; - AprilTagFieldLayout tagLayout = JsonConstants.aprilTagConstants.getTagLayout(); + Field tagLayout = JsonConstants.aprilTagConstants.getTagLayout(); CameraConfig[] cameraConfigs = null; switch (Constants.currentMode) { case REAL: @@ -218,9 +221,9 @@ public boolean isLoggingSingleTags() { drive::addVisionMeasurement, tagLayout, gainConstants, - CameraConfig.fixed(replayIO, Transform3d.kZero), - CameraConfig.fixed(replayIO, Transform3d.kZero), - CameraConfig.fixed(replayIO, Transform3d.kZero)); + CameraConfig.fixed(replayIO, Transform3d.ZERO), + CameraConfig.fixed(replayIO, Transform3d.ZERO), + CameraConfig.fixed(replayIO, Transform3d.ZERO)); } } diff --git a/src/main/java/frc/robot/Main.java b/src/main/java/frc/robot/Main.java deleted file mode 100644 index b5169129..00000000 --- a/src/main/java/frc/robot/Main.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2021-2026 Littleton Robotics -// http://github.com/Mechanical-Advantage -// -// Use of this source code is governed by a BSD -// license that can be found in the LICENSE file -// at the root directory of this project. - -package frc.robot; - -import org.wpilib.framework.RobotBase; -import org.wpilib.framework.TimedRobot; - -/** - * Do NOT add any static variables to this class, or any initialization at all. Unless you know what - * you are doing, do not modify this file except to change the parameter class to the startRobot - * call. - */ -public final class Main { - private Main() {} - - /** - * Main initialization function. Do not perform any initialization here. - * - *

If you change your main robot class, change the parameter type. - */ - public static void main(String... args) { - RobotBase.startRobot(TimedRobot.class); - } -} diff --git a/src/main/java/frc/robot/Robot.java b/src/main/java/frc/robot/Robot.java index f6c4b99d..cd192941 100644 --- a/src/main/java/frc/robot/Robot.java +++ b/src/main/java/frc/robot/Robot.java @@ -17,8 +17,11 @@ import org.wpilib.math.geometry.Rotation2d; import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.system.RobotController; +import org.wpilib.telemetry.Telemetry; +import org.wpilib.tunable.TunableBoolean; +import org.wpilib.tunable.TunableDouble; +import org.wpilib.tunable.Tunables; import org.wpilib.simulation.DriverStationSim; -import org.wpilib.smartdashboard.SmartDashboard; import org.wpilib.command2.Command; import org.wpilib.command2.CommandScheduler; import frc.robot.constants.FeatureFlags; @@ -26,7 +29,7 @@ import org.littletonrobotics.junction.LogFileUtil; import org.littletonrobotics.junction.LoggedRobot; import org.littletonrobotics.junction.Logger; -import org.littletonrobotics.junction.networktables.LoggedDashboardChooser; +import org.littletonrobotics.junction.networktables.LoggedNetworkChooser; import org.littletonrobotics.junction.networktables.NT4Publisher; import org.littletonrobotics.junction.wpilog.WPILOGReader; import org.littletonrobotics.junction.wpilog.WPILOGWriter; @@ -89,7 +92,7 @@ public Robot() { // This got our mean cycle time (admittedly while not seeing any tags) down to 15ms } - DriverStationBackend.silenceJoystickConnectionWarning(true); + DriverStationBackend.silenceJoystickConnectionAlert(true); // Start AdvantageKit logger Logger.start(); @@ -220,32 +223,42 @@ private static class AutoTestingSimulation { // from. It will then run the appropriate simulation based on the selected command and alliance // station. - LoggedDashboardChooser allianceStationChooser; + LoggedNetworkChooser allianceStationChooser; Robot robot; + private final TunableBoolean startAuto = + Tunables.addBoolean(AUTO_TESTING_PREFIX + "StartAuto", false); + + private final TunableBoolean stopAuto = + Tunables.addBoolean(AUTO_TESTING_PREFIX + "StopAuto", false); + + private final TunableBoolean setPos = + Tunables.addBoolean(AUTO_TESTING_PREFIX + "StopAuto", false); + + private final TunableDouble setPosX = + Tunables.addDouble(AUTO_TESTING_PREFIX + "StopAuto", 0.0); + + private final TunableDouble setPosY = + Tunables.addDouble(AUTO_TESTING_PREFIX + "StopAuto", 0.0); + + private final TunableDouble setPosTheta = + Tunables.addDouble(AUTO_TESTING_PREFIX + "StopAuto", 0.0); + public AutoTestingSimulation(Robot robot) { this.robot = robot; // Initialize the auto testing simulation, set up network table listeners, etc. allianceStationChooser = - new LoggedDashboardChooser<>(AUTO_TESTING_PREFIX + "AllianceStation"); - allianceStationChooser.addDefaultOption("Unknown", AllianceStationID.UNKNOWN); - allianceStationChooser.addOption("Red 1", AllianceStationID.RED_1); - allianceStationChooser.addOption("Red 2", AllianceStationID.RED_2); - allianceStationChooser.addOption("Red 3", AllianceStationID.RED_3); - allianceStationChooser.addOption("Blue 1", AllianceStationID.BLUE_1); - allianceStationChooser.addOption("Blue 2", AllianceStationID.BLUE_2); - allianceStationChooser.addOption("Blue 3", AllianceStationID.BLUE_3); - - SmartDashboard.putBoolean(AUTO_TESTING_PREFIX + "RobotEnabled", false); - SmartDashboard.putBoolean(AUTO_TESTING_PREFIX + "AutoEnabled", false); - - SmartDashboard.putBoolean(AUTO_TESTING_PREFIX + "StartAuto", false); - SmartDashboard.putBoolean(AUTO_TESTING_PREFIX + "StopAuto", false); - - SmartDashboard.putBoolean(AUTO_TESTING_PREFIX + "SetPos", false); - SmartDashboard.putNumber(AUTO_TESTING_PREFIX + "SetPosX", 0.0); - SmartDashboard.putNumber(AUTO_TESTING_PREFIX + "SetPosY", 0.0); - SmartDashboard.putNumber(AUTO_TESTING_PREFIX + "SetPosTheta", 0.0); + new LoggedNetworkChooser<>(AUTO_TESTING_PREFIX + "AllianceStation"); + allianceStationChooser.addDefault("Unknown", AllianceStationID.UNKNOWN); + allianceStationChooser.add("Red 1", AllianceStationID.RED_1); + allianceStationChooser.add("Red 2", AllianceStationID.RED_2); + allianceStationChooser.add("Red 3", AllianceStationID.RED_3); + allianceStationChooser.add("Blue 1", AllianceStationID.BLUE_1); + allianceStationChooser.add("Blue 2", AllianceStationID.BLUE_2); + allianceStationChooser.add("Blue 3", AllianceStationID.BLUE_3); + + Telemetry.log(AUTO_TESTING_PREFIX + "RobotEnabled", false); + Telemetry.log(AUTO_TESTING_PREFIX + "AutoEnabled", false); DriverStationSim.setDsAttached(true); } @@ -255,33 +268,33 @@ public void update() { DriverStationSim.setAllianceStationId(allianceStationChooser.get()); DriverStationSim.notifyNewData(); - if (SmartDashboard.getBoolean(AUTO_TESTING_PREFIX + "StartAuto", false)) { + if (startAuto.get()) { DriverStationSim.setRobotMode(RobotMode.AUTONOMOUS); DriverStationSim.setEnabled(true); - SmartDashboard.putBoolean(AUTO_TESTING_PREFIX + "StartAuto", false); + startAuto.set(false); } - if (SmartDashboard.getBoolean(AUTO_TESTING_PREFIX + "StopAuto", false)) { + if (stopAuto.get()) { DriverStationSim.setRobotMode(RobotMode.TELEOPERATED); DriverStationSim.setEnabled(false); - SmartDashboard.putBoolean(AUTO_TESTING_PREFIX + "StopAuto", false); + stopAuto.set(false); } - if (SmartDashboard.getBoolean(AUTO_TESTING_PREFIX + "SetPos", false)) { - double x = SmartDashboard.getNumber(AUTO_TESTING_PREFIX + "SetPosX", 0.0); - double y = SmartDashboard.getNumber(AUTO_TESTING_PREFIX + "SetPosY", 0.0); - double theta = SmartDashboard.getNumber(AUTO_TESTING_PREFIX + "SetPosTheta", 0.0); + if (setPos.get()) { + double x = setPosX.get(); + double y = setPosY.get(); + double theta = setPosTheta.get(); robot .robotContainer .getDriveSubsystem() .setPose(new Pose2d(x, y, Rotation2d.fromDegrees(theta))); - SmartDashboard.putBoolean(AUTO_TESTING_PREFIX + "SetPos", false); + Telemetry.log(AUTO_TESTING_PREFIX + "SetPos", false); } DriverStationSim.notifyNewData(); - SmartDashboard.putBoolean(AUTO_TESTING_PREFIX + "RobotEnabled", DriverStationBackend.isEnabled()); - SmartDashboard.putBoolean(AUTO_TESTING_PREFIX + "AutoEnabled", DriverStationBackend.isAutonomous()); + Telemetry.log(AUTO_TESTING_PREFIX + "RobotEnabled", DriverStationBackend.isEnabled()); + Telemetry.log(AUTO_TESTING_PREFIX + "AutoEnabled", DriverStationBackend.isAutonomous()); } } } diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java index 224e0272..5f1d55eb 100644 --- a/src/main/java/frc/robot/RobotContainer.java +++ b/src/main/java/frc/robot/RobotContainer.java @@ -45,7 +45,7 @@ import frc.robot.subsystems.turret.TurretSubsystem; import java.util.Optional; import org.littletonrobotics.junction.Logger; -import org.littletonrobotics.junction.networktables.LoggedDashboardChooser; +import org.littletonrobotics.junction.networktables.LoggedNetworkChooser; /** * This class is where the bulk of the robot should be declared. Since Command-based is a @@ -67,7 +67,7 @@ public class RobotContainer { private final CoordinationLayer coordinationLayer; // Dashboard inputs - private LoggedDashboardChooser autoChooser; + private LoggedNetworkChooser autoChooser; // JSON jsonHandler private JSONHandler jsonHandler; @@ -161,7 +161,7 @@ public RobotContainer() { drive.ifPresentOrElse( this::createAutoChooser, () -> { - autoChooser = new LoggedDashboardChooser<>("Auto Choices"); + autoChooser = new LoggedNetworkChooser<>("Auto Choices"); }); if (drive.isPresent()) { @@ -191,9 +191,9 @@ public void updateRobotModel() { coordinationLayer .getTurret() .map(TurretSubsystem::getGoalTurretHeading) - .orElse(Rotation2d.kZero) + .orElse(Rotation2d.ZERO) .minus( - coordinationLayer.getDrive().map(Drive::getPose).orElse(Pose2d.kZero).getRotation()) + coordinationLayer.getDrive().map(Drive::getPose).orElse(Pose2d.ZERO).getRotation()) .minus(Rotation2d.k180deg); Angle hoodAngle = coordinationLayer.getHood().map(HoodSubsystem::getCurrentExitPitch).orElse(Radians.zero()); @@ -290,37 +290,37 @@ void processHTTPRequests() { */ private void createAutoChooser(Drive drive) { // Set up auto routines - autoChooser = new LoggedDashboardChooser<>("Auto Choices"); + autoChooser = new LoggedNetworkChooser<>("Auto Choices"); // Set up SysId routines if (drive != null) { - autoChooser.addOption( + autoChooser.add( "Drive Wheel Radius Characterization", DriveCoordinatorCommands.wrapCommand( driveCoordinator.get(), DriveCommands.wheelRadiusCharacterization(drive))); - autoChooser.addOption( + autoChooser.add( "Drive Simple FF Characterization", DriveCoordinatorCommands.wrapCommand( driveCoordinator.get(), DriveCommands.feedforwardCharacterization(drive))); - autoChooser.addOption( + autoChooser.add( "Drive SysId (Quasistatic Forward)", - drive.sysIdQuasistatic(SysIdRoutine.Direction.kForward)); - autoChooser.addOption( + drive.sysIdQuasistatic(SysIdRoutine.Direction.FORWARD)); + autoChooser.add( "Drive SysId (Quasistatic Reverse)", DriveCoordinatorCommands.wrapCommand( - driveCoordinator.get(), drive.sysIdQuasistatic(SysIdRoutine.Direction.kReverse))); - autoChooser.addOption( + driveCoordinator.get(), drive.sysIdQuasistatic(SysIdRoutine.Direction.REVERSE))); + autoChooser.add( "Drive SysId (Dynamic Forward)", DriveCoordinatorCommands.wrapCommand( - driveCoordinator.get(), drive.sysIdDynamic(SysIdRoutine.Direction.kForward))); - autoChooser.addOption( + driveCoordinator.get(), drive.sysIdDynamic(SysIdRoutine.Direction.FORWARD))); + autoChooser.add( "Drive SysId (Dynamic Reverse)", DriveCoordinatorCommands.wrapCommand( - driveCoordinator.get(), drive.sysIdDynamic(SysIdRoutine.Direction.kReverse))); + driveCoordinator.get(), drive.sysIdDynamic(SysIdRoutine.Direction.REVERSE))); } for (var auto : JsonConstants.autos.autoCommands.entrySet()) { - autoChooser.addOption(auto.getKey(), auto.getValue()); + autoChooser.add(auto.getKey(), auto.getValue()); } } diff --git a/src/main/java/frc/robot/ShotCalculations.java b/src/main/java/frc/robot/ShotCalculations.java index 9ca13330..15969f8e 100644 --- a/src/main/java/frc/robot/ShotCalculations.java +++ b/src/main/java/frc/robot/ShotCalculations.java @@ -238,7 +238,7 @@ public record MapBasedShotInfo( * motion using time of flight. * * @param robotPose The current robot position - * @param robotRelativeChassisSpeeds The ROBOT CENTRIC chassis speeds of the robot + * @param robotRelativeChassisVelocities The ROBOT CENTRIC chassis speeds of the robot * @param fieldRelativeShooterVelocity the velocity of the shooter, field relative, as a * Translation2d. * @param target the ShotTarget to aim for @@ -246,7 +246,7 @@ public record MapBasedShotInfo( */ public static MapBasedShotInfo calculateShotFromMap( Pose2d robotPose, - ChassisVelocities robotRelativeChassisSpeeds, + ChassisVelocities robotRelativeChassisVelocities, Translation2d fieldRelativeShooterVelocity, ShotTarget target) { Translation2d targetPosition = target.getTranslation(); @@ -256,9 +256,9 @@ public static MapBasedShotInfo calculateShotFromMap( Pose2d lookaheadPose = robotPose.plus( new Twist2d( - robotRelativeChassisSpeeds.vx * lookaheadTimeSeconds, - robotRelativeChassisSpeeds.vy * lookaheadTimeSeconds, - robotRelativeChassisSpeeds.omega * lookaheadTimeSeconds).exp()); + robotRelativeChassisVelocities.vx * lookaheadTimeSeconds, + robotRelativeChassisVelocities.vy * lookaheadTimeSeconds, + robotRelativeChassisVelocities.omega * lookaheadTimeSeconds).exp()); Logger.recordOutput("ShotCalculations/MapBased/lookaheadPose", lookaheadPose); @@ -406,7 +406,7 @@ public static MapBasedShotInfo calculateShotFromMap( double hoodAngleRadians = map.hoodAngleRadiansByDistanceMeters().get(virtualDistanceXYMeters); double shooterRPM = map.rpmByDistanceMeters().get(virtualDistanceXYMeters); - Rotation2d yaw = virtualTarget.minus(shooterPose.getTranslation()).getAngle(); + Rotation2d yaw = virtualTarget.minus(shooterPose.getTranslation()).getAngle().get(); MapBasedShotInfo shot = new MapBasedShotInfo(hoodAngleRadians, shooterRPM, yaw, isShotReal); Logger.recordOutput("ShotCalculations/MapBased/Shot", shot); diff --git a/src/main/java/frc/robot/autogen/Field.java b/src/main/java/frc/robot/autogen/Field.java index bd1e96c9..506bbc36 100644 --- a/src/main/java/frc/robot/autogen/Field.java +++ b/src/main/java/frc/robot/autogen/Field.java @@ -26,7 +26,7 @@ private Field() {} /** Initializes HAL and loads all robot constants for the active (config.json) environment. */ public static void initialize() { - HAL.initialize(500, 0); + HAL.initialize(); JsonConstants.loadConstants(); } diff --git a/src/main/java/frc/robot/commands/DriveCommands.java b/src/main/java/frc/robot/commands/DriveCommands.java index 816c4a65..602ccd77 100644 --- a/src/main/java/frc/robot/commands/DriveCommands.java +++ b/src/main/java/frc/robot/commands/DriveCommands.java @@ -53,8 +53,8 @@ private static Translation2d getLinearVelocityFromJoysticks(double x, double y) linearMagnitude = linearMagnitude * linearMagnitude; // Return new linear velocity - return new Pose2d(Translation2d.kZero, linearDirection) - .transformBy(new Transform2d(linearMagnitude, 0.0, Rotation2d.kZero)) + return new Pose2d(Translation2d.ZERO, linearDirection) + .transformBy(new Transform2d(linearMagnitude, 0.0, Rotation2d.ZERO)) .getTranslation(); } @@ -285,7 +285,7 @@ public static Command wheelRadiusCharacterization(Drive drive) { private static class WheelRadiusCharacterizationState { double[] positions = new double[4]; - Rotation2d lastAngle = Rotation2d.kZero; + Rotation2d lastAngle = Rotation2d.ZERO; double gyroDelta = 0.0; } } diff --git a/src/main/java/frc/robot/constants/AprilTagConstants.java b/src/main/java/frc/robot/constants/AprilTagConstants.java index c5258f36..bb7db174 100644 --- a/src/main/java/frc/robot/constants/AprilTagConstants.java +++ b/src/main/java/frc/robot/constants/AprilTagConstants.java @@ -1,7 +1,8 @@ package frc.robot.constants; import coppercore.parameter_tools.json.annotations.JSONExclude; -import org.wpilib.vision.apriltag.AprilTagFieldLayout; +import org.wpilib.fields.Field; +import org.wpilib.fields.Fields; import org.wpilib.system.Filesystem; import java.io.IOException; import java.nio.file.Path; @@ -28,22 +29,12 @@ public String getJsonFilename() { public final FieldType fieldType = FieldType.WELDED; - @JSONExclude private AprilTagFieldLayout cachedLayout; + @JSONExclude private Field cachedLayout; - public AprilTagFieldLayout getTagLayout() { + public Field getTagLayout() { if (cachedLayout == null) { - try { - Path p = - Path.of( - Filesystem.getDeployDirectory().getPath(), - "apriltags", - fieldType.getJsonFilename()); - cachedLayout = new AprilTagFieldLayout(p); - } catch (IOException e) { - throw new RuntimeException(e); - } + cachedLayout = Fields.FRC_2026_REBUILT_ANDY_MARK.loadField(); } - return cachedLayout; } } diff --git a/src/main/java/frc/robot/constants/JsonConstants.java b/src/main/java/frc/robot/constants/JsonConstants.java index ca3c67fd..485f44bb 100644 --- a/src/main/java/frc/robot/constants/JsonConstants.java +++ b/src/main/java/frc/robot/constants/JsonConstants.java @@ -5,6 +5,8 @@ import static org.wpilib.units.Units.RotationsPerSecondPerSecond; import static org.wpilib.units.Units.Second; +import org.wpilib.driverstation.internal.DriverStationBackend; + import com.therekrab.autopilot.APConstraints; import com.therekrab.autopilot.APConstraintsTypeAdapter; import com.therekrab.autopilot.APTarget; diff --git a/src/main/java/frc/robot/constants/ManualModeConstants.java b/src/main/java/frc/robot/constants/ManualModeConstants.java index f81dfe07..b502aac5 100644 --- a/src/main/java/frc/robot/constants/ManualModeConstants.java +++ b/src/main/java/frc/robot/constants/ManualModeConstants.java @@ -9,11 +9,11 @@ public class ManualModeConstants { public final Distance assumedPassDistance = Meters.of(4.0); - public final Rotation2d bluePassHeading = Rotation2d.kZero; + public final Rotation2d bluePassHeading = Rotation2d.ZERO; public final Rotation2d redPassHeading = Rotation2d.k180deg; public final Distance assumedHubDistance = Meters.of(3.1); public final Rotation2d blueHubHeading = Rotation2d.k180deg; - public final Rotation2d redHubHeading = Rotation2d.kZero; + public final Rotation2d redHubHeading = Rotation2d.ZERO; } diff --git a/src/main/java/frc/robot/constants/RobotInfo.java b/src/main/java/frc/robot/constants/RobotInfo.java index ac7e6640..d56d5a2b 100644 --- a/src/main/java/frc/robot/constants/RobotInfo.java +++ b/src/main/java/frc/robot/constants/RobotInfo.java @@ -31,8 +31,6 @@ public class RobotInfo { // Private here, everyone else should use the CANBus object below private String canivoreBusName = "canivore"; - private String logFilePath = "./logs/robot_log.hoot"; - public Mass robotMass = Kilograms.of(74.088); public MomentOfInertia robotMOI = KilogramSquareMeters.of(6.883); public Double wheelCof = 1.2; @@ -91,7 +89,7 @@ public final CANdiConfiguration buildHomingSwitchConfig() { @AfterJsonLoad public void loadFieldsFromJSON() { - CANBus = new CANBus(canivoreBusName, logFilePath); + CANBus = new CANBus(canivoreBusName); ODOMETRY_FREQUENCY = CANBus.isNetworkFD() ? 250.0 : 100.0; batteryVoltageAlert = diff --git a/src/main/java/frc/robot/constants/ShotMaps.java b/src/main/java/frc/robot/constants/ShotMaps.java index 53da2e0e..401b6b93 100644 --- a/src/main/java/frc/robot/constants/ShotMaps.java +++ b/src/main/java/frc/robot/constants/ShotMaps.java @@ -14,7 +14,7 @@ import org.wpilib.units.measure.AngularVelocity; import org.wpilib.units.measure.Distance; import org.wpilib.units.measure.Time; -import org.wpilib.smartdashboard.SmartDashboard; +import org.wpilib.telemetry.Telemetry; import org.wpilib.command2.Command; import org.wpilib.command2.InstantCommand; import java.util.Arrays; @@ -214,9 +214,9 @@ public void publishTuningValues() { }) .ignoringDisable(true); - SmartDashboard.putData("ShotMapTuning/addHubDataPoint", addPointToHubMapCommand); - SmartDashboard.putData("ShotMapTuning/addPassDataPoint", addPointToPassingMapCommand); - SmartDashboard.putData("ShotMapTuning/updateMechanismDelay", updateMechanismDelayCommand); + Telemetry.log("ShotMapTuning/addHubDataPoint", addPointToHubMapCommand); + Telemetry.log("ShotMapTuning/addPassDataPoint", addPointToPassingMapCommand); + Telemetry.log("ShotMapTuning/updateMechanismDelay", updateMechanismDelayCommand); } /** ShotMap for shooting at the hub */ diff --git a/src/main/java/frc/robot/constants/drive/PhysicalDriveConstants.java b/src/main/java/frc/robot/constants/drive/PhysicalDriveConstants.java index 7bed9728..61079cf3 100644 --- a/src/main/java/frc/robot/constants/drive/PhysicalDriveConstants.java +++ b/src/main/java/frc/robot/constants/drive/PhysicalDriveConstants.java @@ -227,7 +227,7 @@ public void finishLoadingConstants() { DrivetrainConstants = new SwerveDrivetrainConstants() - .withCANBusName(JsonConstants.robotInfo.CANBus.getName()) + .withNetwork(JsonConstants.robotInfo.CANBus) .withPigeon2Id(JsonConstants.canBusAssignment.kPigeonId) .withPigeon2Configs(pigeonConfigs); var constantCreator = diff --git a/src/main/java/frc/robot/coordination/MatchState.java b/src/main/java/frc/robot/coordination/MatchState.java index 41d26d3c..5bfc4ac9 100644 --- a/src/main/java/frc/robot/coordination/MatchState.java +++ b/src/main/java/frc/robot/coordination/MatchState.java @@ -7,8 +7,8 @@ import org.wpilib.driverstation.MatchType; import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.system.Timer; +import org.wpilib.telemetry.Telemetry; import org.wpilib.simulation.DriverStationSim; -import org.wpilib.smartdashboard.SmartDashboard; import frc.robot.Constants; import frc.robot.Constants.Mode; import frc.robot.constants.JsonConstants; @@ -17,7 +17,7 @@ import org.littletonrobotics.junction.AutoLogOutput; import org.littletonrobotics.junction.AutoLogOutputManager; import org.littletonrobotics.junction.Logger; -import org.littletonrobotics.junction.networktables.LoggedDashboardChooser; +import org.littletonrobotics.junction.networktables.LoggedNetworkChooser; /** * The MatchState class handles tracking the state of the match and indicating when we can score vs. @@ -30,7 +30,7 @@ public class MatchState { private MatchShift currentShift = MatchShift.Unknown; private boolean canScore = true; - private LoggedDashboardChooser matchTypeChooser; + private LoggedNetworkChooser matchTypeChooser; private final Timer preciseMatchTimer = new Timer(); @@ -42,7 +42,7 @@ public class MatchState { private boolean hasTeleopEnabled = false; /** - * @return {@code true} if we are in a match (FMS is attached or DriverStation.getMatchType() + * @return {@code true} if we are in a match (FMS is attached or MatchState.getMatchType() * return Practice, Qualification, or Elimination), {@code false} otherwise */ @AutoLogOutput(key = "MatchState/isInMatch") @@ -50,9 +50,9 @@ public boolean isInMatch() { Logger.recordOutput("MatchState/matchType", DriverStationBackend.getMatchType()); // Hardcode true for shop testing; getMatchType doesn't return a correct value here return true; - // || DriverStation.getMatchType() == DriverStation.MatchType.Practice - // || DriverStation.getMatchType() == DriverStation.MatchType.Qualification - // || DriverStation.getMatchType() == DriverStation.MatchType.Elimination; + // || MatchState.getMatchType() == MatchType.PRACTICE + // || MatchState.getMatchType() == MatchType.QUALIFICATION + // || MatchState.getMatchType() == MatchType.ELIMINATION; } public enum MatchShift { @@ -123,17 +123,17 @@ public boolean isOurHubActive(Optional autoWinner) { public MatchState() { AutoLogOutputManager.addObject(this); - SmartDashboard.putBoolean("matchState/manualRedOverride", false); - SmartDashboard.putBoolean("matchState/manualBlueOverride", false); + Telemetry.log("matchState/manualRedOverride", false); + Telemetry.log("matchState/manualBlueOverride", false); if (Constants.currentMode == Mode.SIM) { - matchTypeChooser = new LoggedDashboardChooser<>("MatchState/MatchType"); + matchTypeChooser = new LoggedNetworkChooser<>("MatchState/MatchType"); for (var matchType : MatchType.values()) { if (matchType == MatchType.NONE) { - matchTypeChooser.addDefaultOption(matchType.name(), matchType); + matchTypeChooser.addDefault(matchType.name(), matchType); } else { - matchTypeChooser.addOption(matchType.name(), matchType); + matchTypeChooser.add(matchType.name(), matchType); } } } diff --git a/src/main/java/frc/robot/generated/TunerConstants.java b/src/main/java/frc/robot/generated/TunerConstants.java index 651984b8..63f5d6dd 100644 --- a/src/main/java/frc/robot/generated/TunerConstants.java +++ b/src/main/java/frc/robot/generated/TunerConstants.java @@ -78,7 +78,7 @@ public class TunerConstants { // CAN bus that the devices are located on; // All swerve devices must share the same CAN bus - public static final CANBus kCANBus = new CANBus("canivore", "./logs/example.hoot"); + public static final CANBus kCANBus = new CANBus("canivore"); // Theoretical free speed (m/s) at 12 V applied output; // This needs to be tuned to your individual robot @@ -106,7 +106,7 @@ public class TunerConstants { public static final SwerveDrivetrainConstants DrivetrainConstants = new SwerveDrivetrainConstants() - .withCANBusName(kCANBus.getName()) + .withNetwork(kCANBus) .withPigeon2Id(kPigeonId) .withPigeon2Configs(pigeonConfigs); diff --git a/src/main/java/frc/robot/subsystems/climber/ClimberState.java b/src/main/java/frc/robot/subsystems/climber/ClimberState.java index 51b68852..b3cfe6b5 100644 --- a/src/main/java/frc/robot/subsystems/climber/ClimberState.java +++ b/src/main/java/frc/robot/subsystems/climber/ClimberState.java @@ -57,7 +57,7 @@ public void periodic(StateMachine stateMachine, ClimberSubsyst public static class TestModeState extends ClimberState { @Override public void periodic(StateMachine stateMachine, ClimberSubsystem climber) { - climber.testPeriodic(); + climber.utilityPeriodic(); } } diff --git a/src/main/java/frc/robot/subsystems/climber/ClimberSubsystem.java b/src/main/java/frc/robot/subsystems/climber/ClimberSubsystem.java index 51a46d2a..8fc5d4e3 100644 --- a/src/main/java/frc/robot/subsystems/climber/ClimberSubsystem.java +++ b/src/main/java/frc/robot/subsystems/climber/ClimberSubsystem.java @@ -223,7 +223,7 @@ public void monitoredPeriodic() { } } - protected void testPeriodic() { + protected void utilityPeriodic() { switch (testModeManager.getTestMode()) { case ClimberClosedLoopTuning -> { LoggedTunableNumber.ifChanged( diff --git a/src/main/java/frc/robot/subsystems/drive/Drive.java b/src/main/java/frc/robot/subsystems/drive/Drive.java index 643b83e7..915ec314 100644 --- a/src/main/java/frc/robot/subsystems/drive/Drive.java +++ b/src/main/java/frc/robot/subsystems/drive/Drive.java @@ -30,14 +30,13 @@ import org.wpilib.math.numbers.N1; import org.wpilib.math.numbers.N3; import org.wpilib.units.measure.Current; -import org.wpilib.driverstation.Alert; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.util.Alert; import org.wpilib.driverstation.Alliance; import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.system.RobotController; import org.wpilib.system.Timer; +import org.wpilib.telemetry.Telemetry; import org.wpilib.smartdashboard.Field2d; -import org.wpilib.smartdashboard.SmartDashboard; import org.wpilib.command2.Command; import org.wpilib.command2.InstantCommand; import org.wpilib.command2.SubsystemBase; @@ -80,11 +79,11 @@ public class Drive extends SubsystemBase implements DriveTemplate { private final GyroIOInputsAutoLogged gyroInputs = new GyroIOInputsAutoLogged(); private final Module[] modules = new Module[4]; // FL, FR, BL, BR private final SysIdRoutine sysId; - private final Alert gyroDisconnectedAlert = - new Alert("Disconnected gyro, using kinematics as fallback.", Alert.Level.HIGH); + private static final Alert gyroDisconnectedAlert = + new Alert("disconnected_gyro", "Disconnected gyro, using kinematics as fallback.", Alert.Level.HIGH); private SwerveDriveKinematics kinematics = new SwerveDriveKinematics(getModuleTranslations()); - private Rotation2d rawGyroRotation = Rotation2d.kZero; + private Rotation2d rawGyroRotation = Rotation2d.ZERO; private Rotation2d lastGyroYaw = new Rotation2d(); private SwerveModulePosition[] lastModulePositions = // For delta tracking new SwerveModulePosition[] { @@ -94,7 +93,7 @@ public class Drive extends SubsystemBase implements DriveTemplate { new SwerveModulePosition() }; private SwerveDrivePoseEstimator poseEstimator = - new SwerveDrivePoseEstimator(kinematics, rawGyroRotation, lastModulePositions, Pose2d.kZero); + new SwerveDrivePoseEstimator(kinematics, rawGyroRotation, lastModulePositions, Pose2d.ZERO); private PoseEstimator maPoseEstimator = new PoseEstimator(VecBuilder.fill(0.003, 0.003, 0.0002)); @@ -133,7 +132,7 @@ public Drive( }) .ignoringDisable(true); - SmartDashboard.putData("ResetToAutoCurrentLimits", resetToAutoLimitsCommand); + Telemetry.log("ResetToAutoCurrentLimits", resetToAutoLimitsCommand); // Usage reporting for swerve template HAL.reportUsage("RobotDrive", "Swerve_AdvantageKit"); @@ -145,12 +144,12 @@ public Drive( // AutoBuilder.configure( // this::getPose, // this::setPose, - // this::getChassisSpeeds, + // this::getChassisVelocities, // this::runVelocity, // new PPHolonomicDriveController( // new PIDConstants(5.0, 0.0, 0.0), new PIDConstants(5.0, 0.0, 0.0)), // PP_CONFIG, - // () -> DriverStation.getAlliance().orElse(Alliance.Blue) == Alliance.Red, + // () -> MatchState.getAlliance().orElse(Alliance.BLUE) == Alliance.RED, // this); // Pathfinding.setPathfinder(new LocalADStarAK()); PathPlannerLogging.setLogActivePathCallback( @@ -177,7 +176,7 @@ public Drive( // Since Drive is placed within an Optional, it can't be found in a recursive down from Robot AutoLogOutputManager.addObject(this); - SmartDashboard.putData("Field2d", field2d); + Telemetry.log("Field2d", field2d); } @Override @@ -212,7 +211,7 @@ public void periodic() { double[] sampleTimestamps = modules[0].getOdometryTimestamps(); // All signals are sampled together int sampleCount = sampleTimestamps.length; - Pose2d totalDeltaPose = Pose2d.kZero; + Pose2d totalDeltaPose = Pose2d.ZERO; for (int i = 0; i < sampleCount; i++) { // Read wheel positions and deltas from each module @@ -263,7 +262,7 @@ public void periodic() { // Apply update if (JsonConstants.featureFlags.useMAPoseEstimator) { - Twist2d totalTwist = totalDeltaPose.minus(Pose2d.kZero).log(); + Twist2d totalTwist = totalDeltaPose.minus(Pose2d.ZERO).log(); lastGyroYaw = gyroInputs.connected ? gyroInputs.yawPosition : rawGyroRotation; maPoseEstimator.addDriveData(Timer.getTimestamp(), totalTwist); } @@ -293,7 +292,7 @@ public void runVelocity(ChassisVelocities speeds) { // Log unoptimized setpoints and setpoint speeds Logger.recordOutput("SwerveStates/Setpoints", setpointStates); - Logger.recordOutput("SwerveChassisSpeeds/Setpoints", discreteSpeeds); + Logger.recordOutput("SwerveChassisVelocities/Setpoints", discreteSpeeds); // Send setpoints to modules for (int i = 0; i < 4; i++) { @@ -367,7 +366,7 @@ public void stop() { public void stopWithX() { Rotation2d[] headings = new Rotation2d[4]; for (int i = 0; i < 4; i++) { - headings[i] = getModuleTranslations()[i].getAngle(); + headings[i] = getModuleTranslations()[i].getAngle().get(); } kinematics.resetHeadings(headings); stop(); @@ -532,7 +531,7 @@ public void seedHeadingForward() { // Red alliance is "flipped" (forward is -x) case RED -> Rotation2d.k180deg; // Blue alliance is +x forward - case BLUE -> Rotation2d.kZero; + case BLUE -> Rotation2d.ZERO; }; setPose(new Pose2d(currentPose.getX(), currentPose.getY(), heading)); diff --git a/src/main/java/frc/robot/subsystems/drive/DriveCoordinator.java b/src/main/java/frc/robot/subsystems/drive/DriveCoordinator.java index 33628152..d9ad770f 100644 --- a/src/main/java/frc/robot/subsystems/drive/DriveCoordinator.java +++ b/src/main/java/frc/robot/subsystems/drive/DriveCoordinator.java @@ -177,7 +177,7 @@ public void periodic() { long startTimeUs = RobotController.getTime(); if (testModeManager.isInTestMode()) { - testPeriodic(); + utilityPeriodic(); } // Maybe decide if we want to check if it is finished before or after executing. @@ -202,7 +202,7 @@ public void periodic() { } } - public void testPeriodic() { + public void utilityPeriodic() { switch (testModeManager.getTestMode()) { case DriveGainsTuning: steerGains.ifChanged(hashCode(), drive::setSteerGains); diff --git a/src/main/java/frc/robot/subsystems/drive/GyroIO.java b/src/main/java/frc/robot/subsystems/drive/GyroIO.java index be3b1ccb..b70ea26a 100644 --- a/src/main/java/frc/robot/subsystems/drive/GyroIO.java +++ b/src/main/java/frc/robot/subsystems/drive/GyroIO.java @@ -14,7 +14,7 @@ public interface GyroIO { @AutoLog public static class GyroIOInputs { public boolean connected = false; - public Rotation2d yawPosition = Rotation2d.kZero; + public Rotation2d yawPosition = Rotation2d.ZERO; public double yawVelocityRadPerSec = 0.0; public double[] odometryYawTimestamps = new double[] {}; public Rotation2d[] odometryYawPositions = new Rotation2d[] {}; diff --git a/src/main/java/frc/robot/subsystems/drive/Module.java b/src/main/java/frc/robot/subsystems/drive/Module.java index c429a8e0..3177c929 100644 --- a/src/main/java/frc/robot/subsystems/drive/Module.java +++ b/src/main/java/frc/robot/subsystems/drive/Module.java @@ -16,8 +16,7 @@ import org.wpilib.math.kinematics.SwerveModuleVelocity; import org.wpilib.math.util.Units; import org.wpilib.units.measure.Current; -import org.wpilib.annotation.NoDiscard; -import org.wpilib.driverstation.Alert; +import org.wpilib.util.Alert; import org.wpilib.system.RobotController; import frc.robot.Constants; import frc.robot.Constants.Mode; @@ -48,13 +47,16 @@ public Module( this.constants = constants; driveDisconnectedAlert = new Alert( + "disconnected_drive_module_" + Integer.toString(index), "Disconnected drive motor on module " + Integer.toString(index) + ".", Alert.Level.HIGH); turnDisconnectedAlert = new Alert( + "disconnected_turn_module_" + Integer.toString(index), "Disconnected turn motor on module " + Integer.toString(index) + ".", Alert.Level.HIGH); turnEncoderDisconnectedAlert = new Alert( + "disconnected_turn_encoder_module_" + Integer.toString(index), "Disconnected turn encoder on module " + Integer.toString(index) + ".", Alert.Level.HIGH); @@ -112,7 +114,7 @@ public void runSetpoint(SwerveModuleVelocity state) { /** Runs the module with the specified output while controlling to zero degrees. */ public void runCharacterization(double output) { io.setDriveOpenLoop(output); - io.setTurnPosition(Rotation2d.kZero); + io.setTurnPosition(Rotation2d.ZERO); } /** Disables all outputs to motors. */ diff --git a/src/main/java/frc/robot/subsystems/drive/ModuleIO.java b/src/main/java/frc/robot/subsystems/drive/ModuleIO.java index 4eb70685..2c362b1c 100644 --- a/src/main/java/frc/robot/subsystems/drive/ModuleIO.java +++ b/src/main/java/frc/robot/subsystems/drive/ModuleIO.java @@ -23,8 +23,8 @@ public static class ModuleIOInputs { public boolean turnConnected = false; public boolean turnEncoderConnected = false; - public Rotation2d turnAbsolutePosition = Rotation2d.kZero; - public Rotation2d turnPosition = Rotation2d.kZero; + public Rotation2d turnAbsolutePosition = Rotation2d.ZERO; + public Rotation2d turnPosition = Rotation2d.ZERO; public double turnVelocityRadPerSec = 0.0; public double turnAppliedVolts = 0.0; public double turnCurrentAmps = 0.0; diff --git a/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFX.java b/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFX.java index 65723c9f..bd0819d7 100644 --- a/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFX.java +++ b/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFX.java @@ -99,11 +99,11 @@ public class ModuleIOTalonFX implements ModuleIO { // Connection debouncers private final Debouncer driveConnectedDebounce = - new Debouncer(0.5, Debouncer.DebounceType.kFalling); + new Debouncer(0.5, Debouncer.DebounceType.FALLING); private final Debouncer turnConnectedDebounce = - new Debouncer(0.5, Debouncer.DebounceType.kFalling); + new Debouncer(0.5, Debouncer.DebounceType.FALLING); private final Debouncer turnEncoderConnectedDebounce = - new Debouncer(0.5, Debouncer.DebounceType.kFalling); + new Debouncer(0.5, Debouncer.DebounceType.FALLING); public ModuleIOTalonFX( SwerveModuleConstants diff --git a/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFXS.java b/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFXS.java index bddb582a..541c1dc5 100644 --- a/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFXS.java +++ b/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFXS.java @@ -73,11 +73,11 @@ public class ModuleIOTalonFXS implements ModuleIO { // Connection debouncers private final Debouncer driveConnectedDebounce = - new Debouncer(0.5, Debouncer.DebounceType.kFalling); + new Debouncer(0.5, Debouncer.DebounceType.FALLING); private final Debouncer turnConnectedDebounce = - new Debouncer(0.5, Debouncer.DebounceType.kFalling); + new Debouncer(0.5, Debouncer.DebounceType.FALLING); private final Debouncer turnEncoderConnectedDebounce = - new Debouncer(0.5, Debouncer.DebounceType.kFalling); + new Debouncer(0.5, Debouncer.DebounceType.FALLING); public ModuleIOTalonFXS( SwerveModuleConstants diff --git a/src/main/java/frc/robot/subsystems/hood/HoodState.java b/src/main/java/frc/robot/subsystems/hood/HoodState.java index 7dcc00a8..bd189f44 100644 --- a/src/main/java/frc/robot/subsystems/hood/HoodState.java +++ b/src/main/java/frc/robot/subsystems/hood/HoodState.java @@ -95,7 +95,7 @@ public void periodic(StateMachine stateMachine, HoodSubsystem hoo public static class TestModeState extends HoodState { @Override public void periodic(StateMachine stateMachine, HoodSubsystem hood) { - hood.testPeriodic(); + hood.utilityPeriodic(); } } } diff --git a/src/main/java/frc/robot/subsystems/hood/HoodSubsystem.java b/src/main/java/frc/robot/subsystems/hood/HoodSubsystem.java index d5f14f9b..6322db1e 100644 --- a/src/main/java/frc/robot/subsystems/hood/HoodSubsystem.java +++ b/src/main/java/frc/robot/subsystems/hood/HoodSubsystem.java @@ -23,7 +23,7 @@ import org.wpilib.units.AngularVelocityUnit; import org.wpilib.units.measure.Angle; import org.wpilib.units.measure.AngularVelocity; -import org.wpilib.driverstation.Alert; +import org.wpilib.util.Alert; import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.system.RobotController; import frc.robot.CoordinationLayer.ShotMode; @@ -295,7 +295,7 @@ public void monitoredPeriodic() { * *

This method must be called by the test mode state, as it does not run automatically */ - protected void testPeriodic() { + protected void utilityPeriodic() { switch (testModeManager.getTestMode()) { case HoodClosedLoopTuning -> { LoggedTunableNumber.ifChanged( diff --git a/src/main/java/frc/robot/subsystems/hopper/HopperState.java b/src/main/java/frc/robot/subsystems/hopper/HopperState.java index 3f0b65c7..b63ead95 100644 --- a/src/main/java/frc/robot/subsystems/hopper/HopperState.java +++ b/src/main/java/frc/robot/subsystems/hopper/HopperState.java @@ -36,7 +36,7 @@ public void periodic( public static class TestModeState extends HopperState { @Override public void periodic(StateMachine stateMachine, HopperSubsystem hopper) { - hopper.testPeriodic(); + hopper.utilityPeriodic(); } } } diff --git a/src/main/java/frc/robot/subsystems/hopper/HopperSubsystem.java b/src/main/java/frc/robot/subsystems/hopper/HopperSubsystem.java index 2584dcfc..f538e581 100644 --- a/src/main/java/frc/robot/subsystems/hopper/HopperSubsystem.java +++ b/src/main/java/frc/robot/subsystems/hopper/HopperSubsystem.java @@ -49,7 +49,7 @@ public class HopperSubsystem extends MonitoredSubsystem { private final Debouncer dejamRequiredDebouncer = new Debouncer( - JsonConstants.hopperConstants.dejamDebounceTime.in(Seconds), DebounceType.kRising); + JsonConstants.hopperConstants.dejamDebounceTime.in(Seconds), DebounceType.RISING); private final Timer dejamCooldownTimer = new Timer(); Lazy> tuningModeHelper; @@ -132,7 +132,7 @@ public void monitoredPeriodic() { } } - protected void testPeriodic() { + protected void utilityPeriodic() { tuningModeHelper.get().testPeriodic(testModeManager.getTestMode()); } diff --git a/src/main/java/frc/robot/subsystems/indexer/IndexerState.java b/src/main/java/frc/robot/subsystems/indexer/IndexerState.java index e17cf630..a1520287 100644 --- a/src/main/java/frc/robot/subsystems/indexer/IndexerState.java +++ b/src/main/java/frc/robot/subsystems/indexer/IndexerState.java @@ -19,7 +19,7 @@ public void periodic(StateMachine stateMachine, IndexerSubsyst public static class TestModeState extends IndexerState { @Override public void periodic(StateMachine stateMachine, IndexerSubsystem indexer) { - indexer.testPeriodic(); + indexer.utilityPeriodic(); } } diff --git a/src/main/java/frc/robot/subsystems/indexer/IndexerSubsystem.java b/src/main/java/frc/robot/subsystems/indexer/IndexerSubsystem.java index adfa8a9b..92cfe65c 100644 --- a/src/main/java/frc/robot/subsystems/indexer/IndexerSubsystem.java +++ b/src/main/java/frc/robot/subsystems/indexer/IndexerSubsystem.java @@ -54,7 +54,7 @@ public class IndexerSubsystem extends MonitoredSubsystem { private final Debouncer isAtGoalVelocityDebouncer = new Debouncer( - JsonConstants.indexerConstants.atSetpointDebounceTime.in(Seconds), DebounceType.kFalling); + JsonConstants.indexerConstants.atSetpointDebounceTime.in(Seconds), DebounceType.FALLING); public IndexerSubsystem(MotorIO motor) { this.motor = motor; @@ -148,7 +148,7 @@ public void monitoredPeriodic() { } } - protected void testPeriodic() { + protected void utilityPeriodic() { tuningModeHelper.get().testPeriodic(testModeManager.getTestMode()); } diff --git a/src/main/java/frc/robot/subsystems/shooter/ShooterState.java b/src/main/java/frc/robot/subsystems/shooter/ShooterState.java index 3ee5ed8a..822b5fa9 100644 --- a/src/main/java/frc/robot/subsystems/shooter/ShooterState.java +++ b/src/main/java/frc/robot/subsystems/shooter/ShooterState.java @@ -23,12 +23,12 @@ public void periodic(StateMachine stateMachine, ShooterSubsyst public static class TestModeState extends ShooterState { @Override public void onEntry(StateMachine stateMachine, ShooterSubsystem shooter) { - shooter.testInit(); + shooter.utilityInit(); } @Override public void periodic(StateMachine stateMachine, ShooterSubsystem shooter) { - shooter.testPeriodic(); + shooter.utilityPeriodic(); } } } diff --git a/src/main/java/frc/robot/subsystems/shooter/ShooterSubsystem.java b/src/main/java/frc/robot/subsystems/shooter/ShooterSubsystem.java index 836776e6..f687dc14 100644 --- a/src/main/java/frc/robot/subsystems/shooter/ShooterSubsystem.java +++ b/src/main/java/frc/robot/subsystems/shooter/ShooterSubsystem.java @@ -103,7 +103,7 @@ private enum ShooterAction { private final Debouncer isAtGoalVelocityDebouncer = new Debouncer( - JsonConstants.shooterConstants.atSetpointDebounceTime.in(Seconds), DebounceType.kFalling); + JsonConstants.shooterConstants.atSetpointDebounceTime.in(Seconds), DebounceType.FALLING); // State variables for FF characterization private SimpleRegression ffRegression = new SimpleRegression(); @@ -234,7 +234,7 @@ public void monitoredPeriodic() { } /** Runs when test mode is entered. Should be called by the test mode state. */ - protected void testInit() { + protected void utilityInit() { switch (testModeManager.getTestMode()) { case ShooterFFCharacterization -> { this.ffRegression.clear(); @@ -247,7 +247,7 @@ protected void testInit() { } } - protected void testPeriodic() { + protected void utilityPeriodic() { switch (testModeManager.getTestMode()) { case ShooterClosedLoopTuning -> { slot0TunableGains diff --git a/src/main/java/frc/robot/subsystems/transferroller/TransferRollerState.java b/src/main/java/frc/robot/subsystems/transferroller/TransferRollerState.java index fb8dffc3..f0a57496 100644 --- a/src/main/java/frc/robot/subsystems/transferroller/TransferRollerState.java +++ b/src/main/java/frc/robot/subsystems/transferroller/TransferRollerState.java @@ -23,7 +23,7 @@ public static class TestModeState extends TransferRollerState { public void periodic( StateMachine stateMachine, TransferRollerSubsystem transferRoller) { - transferRoller.testPeriodic(); + transferRoller.utilityPeriodic(); } } diff --git a/src/main/java/frc/robot/subsystems/transferroller/TransferRollerSubsystem.java b/src/main/java/frc/robot/subsystems/transferroller/TransferRollerSubsystem.java index cdd8acf3..815a7ae0 100644 --- a/src/main/java/frc/robot/subsystems/transferroller/TransferRollerSubsystem.java +++ b/src/main/java/frc/robot/subsystems/transferroller/TransferRollerSubsystem.java @@ -40,7 +40,7 @@ public class TransferRollerSubsystem extends MonitoredSubsystem { private final Debouncer shouldDejamDebouncer = new Debouncer( - JsonConstants.transferRollerConstants.dejamTime.in(Seconds), DebounceType.kRising); + JsonConstants.transferRollerConstants.dejamTime.in(Seconds), DebounceType.RISING); // State machine and states private final StateMachine stateMachine; @@ -152,7 +152,7 @@ public void monitoredPeriodic() { } } - protected void testPeriodic() { + protected void utilityPeriodic() { tuningModeHelper.get().testPeriodic(testModeManager.getTestMode()); } diff --git a/src/main/java/frc/robot/subsystems/turret/TurretState.java b/src/main/java/frc/robot/subsystems/turret/TurretState.java index b9b457b8..fe9872be 100644 --- a/src/main/java/frc/robot/subsystems/turret/TurretState.java +++ b/src/main/java/frc/robot/subsystems/turret/TurretState.java @@ -136,7 +136,7 @@ public void periodic(StateMachine stateMachine, TurretSubsystem public static class TestModeState extends TurretState { @Override public void periodic(StateMachine stateMachine, TurretSubsystem turret) { - turret.testPeriodic(); + turret.utilityPeriodic(); } } } diff --git a/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java b/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java index 1cb41e6c..121f0434 100644 --- a/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java +++ b/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java @@ -25,7 +25,6 @@ import org.wpilib.math.interpolation.InterpolatingDoubleTreeMap; import org.wpilib.units.measure.Angle; import org.wpilib.units.measure.AngularVelocity; -import org.wpilib.driverstation.DriverStation; import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.system.RobotController; import frc.robot.Constants; @@ -74,7 +73,7 @@ public static class TurretDependencies { private boolean isHomingSwitchPressed = false; /** The current field-centric heading of the robot, according to the drivetrain pose estimate */ - private Rotation2d robotHeading = Rotation2d.kZero; + private Rotation2d robotHeading = Rotation2d.ZERO; /** * Whether or not the turret should currently stop moving to avoid tearing the intake net or to @@ -141,7 +140,7 @@ public Rotation2d getRobotHeading() { * be updated by the coordinator layer via setGoalHeading. */ @AutoLogOutput(key = "Turret/goalHeading") - private Rotation2d goalTurretHeading = Rotation2d.kZero; + private Rotation2d goalTurretHeading = Rotation2d.ZERO; private final InterpolatingDoubleTreeMap goalAngleOffsetMap = new InterpolatingDoubleTreeMap(); @@ -318,7 +317,7 @@ public void monitoredPeriodic() { * *

This method MUST be called in periodic by the TestModeState */ - protected void testPeriodic() { + protected void utilityPeriodic() { switch (testModeManager.getTestMode()) { case TurretClosedLoopTuning -> { LoggedTunableNumber.ifChanged( diff --git a/src/main/java/frc/robot/util/LocalADStarAK.java b/src/main/java/frc/robot/util/LocalADStarAK.java index 82a51a07..b20b0fd0 100644 --- a/src/main/java/frc/robot/util/LocalADStarAK.java +++ b/src/main/java/frc/robot/util/LocalADStarAK.java @@ -13,7 +13,7 @@ import com.pathplanner.lib.path.PathPoint; import com.pathplanner.lib.pathfinding.LocalADStar; import com.pathplanner.lib.pathfinding.Pathfinder; -import org.wpilib.math.util.Pair; +import org.wpilib.util.Pair; import org.wpilib.math.geometry.Translation2d; import java.util.ArrayList; import java.util.Collections; diff --git a/src/main/java/frc/robot/util/littletonUtil/GeomUtil.java b/src/main/java/frc/robot/util/littletonUtil/GeomUtil.java index 159a88a5..36ef2dde 100644 --- a/src/main/java/frc/robot/util/littletonUtil/GeomUtil.java +++ b/src/main/java/frc/robot/util/littletonUtil/GeomUtil.java @@ -124,7 +124,7 @@ public static Pose3d toPose3d(Transform3d transform) { } /** - * Converts a ChassisSpeeds to a Twist2d by extracting two dimensions (Y and Z). chain + * Converts a ChassisVelocities to a Twist2d by extracting two dimensions (Y and Z). chain * * @param speeds The original translation * @return The resulting translation diff --git a/vendordeps/AdvantageKit.json b/vendordeps/AdvantageKit.json index 177ee85c..3e66592e 100644 --- a/vendordeps/AdvantageKit.json +++ b/vendordeps/AdvantageKit.json @@ -1,9 +1,9 @@ { "fileName": "AdvantageKit.json", "name": "AdvantageKit", - "version": "27.0.0-alpha-4", + "version": "27.0.0-alpha-6", "uuid": "d820cc26-74e3-11ec-90d6-0242ac120003", - "wpilibYear": "2027_alpha5", + "wpilibYear": "2027_alpha7", "mavenUrls": [ "https://frcmaven.wpi.edu/artifactory/littletonrobotics-mvn-release/" ], @@ -12,14 +12,14 @@ { "groupId": "org.littletonrobotics.akit", "artifactId": "akit-java", - "version": "27.0.0-alpha-4" + "version": "27.0.0-alpha-6" } ], "jniDependencies": [ { "groupId": "org.littletonrobotics.akit", "artifactId": "akit-wpilibio", - "version": "27.0.0-alpha-4", + "version": "27.0.0-alpha-6", "skipInvalidPlatforms": false, "isJar": false, "validPlatforms": [ @@ -27,7 +27,8 @@ "linuxx86-64", "linuxarm64", "osxuniversal", - "windowsx86-64" + "windowsx86-64", + "windowsarm64" ] } ], diff --git a/vendordeps/AprilTag.json b/vendordeps/AprilTag.json new file mode 100644 index 00000000..3e5a68c5 --- /dev/null +++ b/vendordeps/AprilTag.json @@ -0,0 +1,91 @@ +{ + "fileName": "AprilTag.json", + "name": "AprilTag", + "version": "1.0.0", + "uuid": "3ac3403d-7f6b-4b5a-a09c-a49a2c32e5a3", + "wpilibYear": "2027_alpha7", + "mavenUrls": [], + "jsonUrl": "", + "javaDependencies": [ + { + "groupId": "org.wpilib.thirdparty.opencv", + "artifactId": "opencv-java", + "version": "2027-4.13.0-3" + }, + { + "groupId": "org.wpilib.apriltag", + "artifactId": "apriltag-java", + "version": "wpilib" + } + ], + "jniDependencies": [ + { + "groupId": "org.wpilib.thirdparty.opencv", + "artifactId": "opencv-cpp", + "version": "2027-4.13.0-3", + "skipInvalidPlatforms": true, + "isJar": false, + "validPlatforms": [ + "linuxsystemcore", + "linuxarm64", + "windowsx86-64", + "windowsarm64", + "linuxx86-64", + "osxuniversal" + ] + }, + { + "groupId": "org.wpilib.apriltag", + "artifactId": "apriltag-cpp", + "version": "wpilib", + "skipInvalidPlatforms": true, + "isJar": false, + "validPlatforms": [ + "linuxsystemcore", + "linuxarm64", + "windowsx86-64", + "windowsarm64", + "linuxx86-64", + "osxuniversal" + ] + } + ], + "cppDependencies": [ + { + "groupId": "org.wpilib.thirdparty.opencv", + "artifactId": "opencv-cpp", + "version": "2027-4.13.0-3", + "libName": "opencv", + "headerClassifier": "headers", + "sourcesClassifier": "sources", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxsystemcore", + "linuxarm64", + "windowsx86-64", + "windowsarm64", + "linuxx86-64", + "osxuniversal" + ] + }, + { + "groupId": "org.wpilib.apriltag", + "artifactId": "apriltag-cpp", + "version": "wpilib", + "libName": "apriltag", + "headerClassifier": "headers", + "sourcesClassifier": "sources", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxsystemcore", + "linuxarm64", + "windowsx86-64", + "windowsarm64", + "linuxx86-64", + "osxuniversal" + ] + } + ] +} \ No newline at end of file diff --git a/vendordeps/CameraServer.json b/vendordeps/CameraServer.json new file mode 100644 index 00000000..a20fe96f --- /dev/null +++ b/vendordeps/CameraServer.json @@ -0,0 +1,114 @@ +{ + "fileName": "CameraServer.json", + "name": "CameraServer", + "version": "1.0.0", + "uuid": "19049c8a-7635-4aca-aa7d-1fdde2c10eed", + "wpilibYear": "2027_alpha7", + "mavenUrls": [], + "jsonUrl": "", + "javaDependencies": [ + { + "groupId": "org.wpilib.thirdparty.opencv", + "artifactId": "opencv-java", + "version": "2027-4.13.0-3" + }, + { + "groupId": "org.wpilib.cscore", + "artifactId": "cscore-java", + "version": "wpilib" + }, + { + "groupId": "org.wpilib.cameraserver", + "artifactId": "cameraserver-java", + "version": "wpilib" + } + ], + "jniDependencies": [ + { + "groupId": "org.wpilib.thirdparty.opencv", + "artifactId": "opencv-cpp", + "version": "2027-4.13.0-3", + "skipInvalidPlatforms": true, + "isJar": false, + "validPlatforms": [ + "linuxsystemcore", + "linuxarm64", + "windowsx86-64", + "windowsarm64", + "linuxx86-64", + "osxuniversal" + ] + }, + { + "groupId": "org.wpilib.cscore", + "artifactId": "cscore-cpp", + "version": "wpilib", + "skipInvalidPlatforms": true, + "isJar": false, + "validPlatforms": [ + "linuxsystemcore", + "linuxarm64", + "windowsx86-64", + "windowsarm64", + "linuxx86-64", + "osxuniversal" + ] + } + ], + "cppDependencies": [ + { + "groupId": "org.wpilib.thirdparty.opencv", + "artifactId": "opencv-cpp", + "version": "2027-4.13.0-3", + "libName": "opencv", + "headerClassifier": "headers", + "sourcesClassifier": "sources", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxsystemcore", + "linuxarm64", + "windowsx86-64", + "windowsarm64", + "linuxx86-64", + "osxuniversal" + ] + }, + { + "groupId": "org.wpilib.cscore", + "artifactId": "cscore-cpp", + "version": "wpilib", + "libName": "cscore", + "headerClassifier": "headers", + "sourcesClassifier": "sources", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxsystemcore", + "linuxarm64", + "windowsx86-64", + "windowsarm64", + "linuxx86-64", + "osxuniversal" + ] + }, + { + "groupId": "org.wpilib.cameraserver", + "artifactId": "cameraserver-cpp", + "version": "wpilib", + "libName": "cameraserver", + "headerClassifier": "headers", + "sourcesClassifier": "sources", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxsystemcore", + "linuxarm64", + "windowsx86-64", + "windowsarm64", + "linuxx86-64", + "osxuniversal" + ] + } + ] +} \ No newline at end of file diff --git a/vendordeps/CommandsV2.json b/vendordeps/CommandsV2.json index 984c221c..ae2b96b4 100644 --- a/vendordeps/CommandsV2.json +++ b/vendordeps/CommandsV2.json @@ -1,46 +1,44 @@ { - "fileName": "CommandsV2.json", - "name": "Commands V2", - "version": "1.0.0", - "uuid": "111e20f7-815e-48f8-9dd6-e675ce75b266", - "wpilibYear": "2027_alpha5", - "mavenUrls": [], - "jsonUrl": "", - "conflictsWith": [ - { - "uuid": "4decdc05-a056-46cf-9561-39449bbb01306", - "errorMessage": "Users can not have both Commands v2 and Commands v3 vendordeps in their robot program.", - "offlineFileName": "CommandsV3.json" - } - ], - "javaDependencies": [ - { - "groupId": "org.wpilib.commandsv2", - "artifactId": "commandsv2-java", - "version": "wpilib" - } - ], - "jniDependencies": [], - "cppDependencies": [ - { - "groupId": "org.wpilib.commandsv2", - "artifactId": "commandsv2-cpp", - "version": "wpilib", - "libName": "commandsv2", - "headerClassifier": "headers", - "sourcesClassifier": "sources", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "linuxsystemcore", - "linuxathena", - "linuxarm32", - "linuxarm64", - "windowsx86-64", - "windowsx86", - "linuxx86-64", - "osxuniversal" - ] - } - ] -} \ No newline at end of file + "fileName": "CommandsV2.json", + "name": "Commands V2", + "version": "1.0.0", + "uuid": "111e20f7-815e-48f8-9dd6-e675ce75b266", + "wpilibYear": "2027_alpha7", + "mavenUrls": [], + "jsonUrl": "", + "conflictsWith": [ + { + "uuid": "4decdc05-a056-46cf-9561-39449bbb01306", + "errorMessage": "Users can not have both Commands v2 and Commands v3 vendordeps in their robot program.", + "offlineFileName": "CommandsV3.json" + } + ], + "javaDependencies": [ + { + "groupId": "org.wpilib.commandsv2", + "artifactId": "commandsv2-java", + "version": "wpilib" + } + ], + "jniDependencies": [], + "cppDependencies": [ + { + "groupId": "org.wpilib.commandsv2", + "artifactId": "commandsv2-cpp", + "version": "wpilib", + "libName": "commandsv2", + "headerClassifier": "headers", + "sourcesClassifier": "sources", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxsystemcore", + "linuxarm64", + "windowsx86-64", + "windowsarm64", + "linuxx86-64", + "osxuniversal" + ] + } + ] +} diff --git a/vendordeps/PathplannerLibSystemCoreAlpha.json b/vendordeps/PathplannerLibSystemCoreAlpha.json index 24d3c8c7..03f38684 100644 --- a/vendordeps/PathplannerLibSystemCoreAlpha.json +++ b/vendordeps/PathplannerLibSystemCoreAlpha.json @@ -1,9 +1,9 @@ { "fileName": "PathplannerLibSystemCoreAlpha.json", "name": "PathplannerLib", - "version": "2027.0.0-alpha-3", + "version": "2027.0.0-alpha-4.1", "uuid": "1b42324f-17c6-4875-8e77-1c312bc8c786", - "wpilibYear": "2027_alpha5", + "wpilibYear": "2027_alpha7", "mavenUrls": [ "https://3015rangerrobotics.github.io/pathplannerlib/repo" ], @@ -12,7 +12,7 @@ { "groupId": "com.pathplanner.lib", "artifactId": "PathplannerLib-java", - "version": "2027.0.0-alpha-3" + "version": "2027.0.0-alpha-4.1" } ], "jniDependencies": [], @@ -20,7 +20,7 @@ { "groupId": "com.pathplanner.lib", "artifactId": "PathplannerLib-cpp", - "version": "2027.0.0-alpha-3", + "version": "2027.0.0-alpha-4.1", "libName": "PathplannerLib", "headerClassifier": "headers", "sharedLibrary": false, diff --git a/vendordeps/Phoenix6-26.50.0-alpha-1.json b/vendordeps/Phoenix6-26.70.0-alpha-2.json similarity index 90% rename from vendordeps/Phoenix6-26.50.0-alpha-1.json rename to vendordeps/Phoenix6-26.70.0-alpha-2.json index f7db60ad..af2ed5f8 100644 --- a/vendordeps/Phoenix6-26.50.0-alpha-1.json +++ b/vendordeps/Phoenix6-26.70.0-alpha-2.json @@ -1,8 +1,8 @@ { - "fileName": "Phoenix6-26.50.0-alpha-1.json", + "fileName": "Phoenix6-26.70.0-alpha-2.json", "name": "CTRE-Phoenix (v6)", - "version": "26.50.0-alpha-1", - "wpilibYear": "2027_alpha5", + "version": "26.70.0-alpha-2", + "wpilibYear": "2027_alpha7", "uuid": "e995de00-2c64-4df5-8831-c1441420ff19", "mavenUrls": [ "https://maven.ctr-electronics.com/release/" @@ -19,14 +19,14 @@ { "groupId": "com.ctre.phoenix6", "artifactId": "wpiapi-java", - "version": "26.50.0-alpha-1" + "version": "26.70.0-alpha-2" } ], "jniDependencies": [ { "groupId": "com.ctre.phoenix6", "artifactId": "api-cpp", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -40,7 +40,7 @@ { "groupId": "com.ctre.phoenix6", "artifactId": "tools", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -54,7 +54,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "api-cpp-sim", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -68,7 +68,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "tools-sim", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -82,7 +82,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simTalonSRX", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -96,7 +96,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simVictorSPX", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -110,7 +110,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simPigeonIMU", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -124,7 +124,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProTalonFX", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -138,7 +138,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProTalonFXS", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -152,7 +152,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANcoder", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -166,7 +166,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProPigeon2", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -180,7 +180,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANrange", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -194,7 +194,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANdi", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -208,7 +208,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANdle", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -224,7 +224,7 @@ { "groupId": "com.ctre.phoenix6", "artifactId": "wpiapi-cpp", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "libName": "CTRE_Phoenix6_WPI", "headerClassifier": "headers", "sharedLibrary": true, @@ -240,7 +240,7 @@ { "groupId": "com.ctre.phoenix6", "artifactId": "tools", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "libName": "CTRE_PhoenixTools", "headerClassifier": "headers", "sharedLibrary": true, @@ -256,7 +256,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "wpiapi-cpp-sim", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "libName": "CTRE_Phoenix6_WPISim", "headerClassifier": "headers", "sharedLibrary": true, @@ -272,7 +272,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "tools-sim", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "libName": "CTRE_PhoenixTools_Sim", "headerClassifier": "headers", "sharedLibrary": true, @@ -288,7 +288,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simTalonSRX", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "libName": "CTRE_SimTalonSRX", "headerClassifier": "headers", "sharedLibrary": true, @@ -304,7 +304,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simVictorSPX", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "libName": "CTRE_SimVictorSPX", "headerClassifier": "headers", "sharedLibrary": true, @@ -320,7 +320,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simPigeonIMU", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "libName": "CTRE_SimPigeonIMU", "headerClassifier": "headers", "sharedLibrary": true, @@ -336,7 +336,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProTalonFX", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "libName": "CTRE_SimProTalonFX", "headerClassifier": "headers", "sharedLibrary": true, @@ -352,7 +352,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProTalonFXS", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "libName": "CTRE_SimProTalonFXS", "headerClassifier": "headers", "sharedLibrary": true, @@ -368,7 +368,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANcoder", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "libName": "CTRE_SimProCANcoder", "headerClassifier": "headers", "sharedLibrary": true, @@ -384,7 +384,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProPigeon2", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "libName": "CTRE_SimProPigeon2", "headerClassifier": "headers", "sharedLibrary": true, @@ -400,7 +400,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANrange", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "libName": "CTRE_SimProCANrange", "headerClassifier": "headers", "sharedLibrary": true, @@ -416,7 +416,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANdi", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "libName": "CTRE_SimProCANdi", "headerClassifier": "headers", "sharedLibrary": true, @@ -432,7 +432,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANdle", - "version": "26.50.0-alpha-1", + "version": "26.70.0-alpha-2", "libName": "CTRE_SimProCANdle", "headerClassifier": "headers", "sharedLibrary": true, diff --git a/vendordeps/REVLib.json b/vendordeps/REVLib.json index 2861f9e2..319cbf60 100644 --- a/vendordeps/REVLib.json +++ b/vendordeps/REVLib.json @@ -1,8 +1,8 @@ { "fileName": "REVLib.json", "name": "REVLib", - "version": "2027.0.0-alpha-6", - "wpilibYear": "2027_alpha5", + "version": "2027.0.0-alpha-8", + "wpilibYear": "2027_alpha7", "uuid": "3f48eb8c-50fe-43a6-9cb7-44c86353c4cb", "mavenUrls": [ "https://maven.revrobotics.com/" @@ -12,14 +12,14 @@ { "groupId": "com.revrobotics.frc", "artifactId": "REVLib-java", - "version": "2027.0.0-alpha-6" + "version": "2027.0.0-alpha-8" } ], "jniDependencies": [ { "groupId": "com.revrobotics.frc", "artifactId": "REVLib-driver", - "version": "2027.0.0-alpha-6", + "version": "2027.0.0-alpha-8", "skipInvalidPlatforms": true, "isJar": false, "validPlatforms": [ @@ -33,7 +33,7 @@ { "groupId": "com.revrobotics.frc", "artifactId": "RevLibBackendDriver", - "version": "2027.0.0-alpha-6", + "version": "2027.0.0-alpha-8", "skipInvalidPlatforms": true, "isJar": false, "validPlatforms": [ @@ -47,7 +47,7 @@ { "groupId": "com.revrobotics.frc", "artifactId": "RevLibWpiBackendDriver", - "version": "2027.0.0-alpha-6", + "version": "2027.0.0-alpha-8", "skipInvalidPlatforms": true, "isJar": false, "validPlatforms": [ @@ -63,7 +63,7 @@ { "groupId": "com.revrobotics.frc", "artifactId": "REVLib-cpp", - "version": "2027.0.0-alpha-6", + "version": "2027.0.0-alpha-8", "libName": "REVLib", "headerClassifier": "headers", "sharedLibrary": false, @@ -79,7 +79,7 @@ { "groupId": "com.revrobotics.frc", "artifactId": "REVLib-driver", - "version": "2027.0.0-alpha-6", + "version": "2027.0.0-alpha-8", "libName": "REVLibDriver", "headerClassifier": "headers", "sharedLibrary": false, @@ -95,7 +95,7 @@ { "groupId": "com.revrobotics.frc", "artifactId": "RevLibBackendDriver", - "version": "2027.0.0-alpha-6", + "version": "2027.0.0-alpha-8", "libName": "BackendDriver", "sharedLibrary": true, "skipInvalidPlatforms": true, @@ -110,7 +110,7 @@ { "groupId": "com.revrobotics.frc", "artifactId": "RevLibWpiBackendDriver", - "version": "2027.0.0-alpha-6", + "version": "2027.0.0-alpha-8", "libName": "REVLibWpi", "sharedLibrary": true, "skipInvalidPlatforms": true, diff --git a/vendordeps/photonlib-v2027.0.0-alpha-2-86-gda55d785.json b/vendordeps/photonlib-v2027.0.0-alpha-2-86-gda55d785.json new file mode 100644 index 00000000..2d40b562 --- /dev/null +++ b/vendordeps/photonlib-v2027.0.0-alpha-2-86-gda55d785.json @@ -0,0 +1,84 @@ +{ + "fileName": "photonlib.json", + "name": "photonlib", + "version": "dev-v2027.0.0-alpha-2-86-gda55d785", + "uuid": "515fe07e-bfc6-11fa-b3de-0242ac130004", + "wpilibYear": "2027_alpha7", + "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": "dev-v2027.0.0-alpha-2-86-gda55d785", + "skipInvalidPlatforms": true, + "isJar": false, + "validPlatforms": [ + "windowsx86-64", + "linuxsystemcore", + "linuxx86-64", + "osxuniversal" + ] + }, + { + "groupId": "org.wpilib.fields", + "artifactId": "fields-cpp", + "version": "wpilib", + "skipInvalidPlatforms": true, + "isJar": false, + "validPlatforms": [ + "windowsx86-64", + "linuxsystemcore", + "linuxx86-64", + "osxuniversal" + ] + } + ], + "cppDependencies": [ + { + "groupId": "org.photonvision", + "artifactId": "photonlib-cpp", + "version": "dev-v2027.0.0-alpha-2-86-gda55d785", + "libName": "photonlib", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxsystemcore", + "linuxx86-64", + "osxuniversal" + ] + }, + { + "groupId": "org.photonvision", + "artifactId": "photontargeting-cpp", + "version": "dev-v2027.0.0-alpha-2-86-gda55d785", + "libName": "photontargeting", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxsystemcore", + "linuxx86-64", + "osxuniversal" + ] + } + ], + "javaDependencies": [ + { + "groupId": "org.photonvision", + "artifactId": "photonlib-java", + "version": "dev-v2027.0.0-alpha-2-86-gda55d785" + }, + { + "groupId": "org.photonvision", + "artifactId": "photontargeting-java", + "version": "dev-v2027.0.0-alpha-2-86-gda55d785" + } + ] +} diff --git a/vendordeps/photonlib.json b/vendordeps/photonlib.json deleted file mode 100644 index cb947f85..00000000 --- a/vendordeps/photonlib.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "fileName": "photonlib.json", - "name": "photonlib", - "version": "v2027.0.0-alpha-2", - "uuid": "515fe07e-bfc6-11fa-b3de-0242ac130004", - "wpilibYear": "2027_alpha5", - "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": "v2027.0.0-alpha-2", - "skipInvalidPlatforms": true, - "isJar": false, - "validPlatforms": [ - "windowsx86-64", - "linuxsystemcore", - "linuxx86-64", - "osxuniversal" - ] - } - ], - "cppDependencies": [ - { - "groupId": "org.photonvision", - "artifactId": "photonlib-cpp", - "version": "v2027.0.0-alpha-2", - "libName": "photonlib", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxsystemcore", - "linuxx86-64", - "osxuniversal" - ] - }, - { - "groupId": "org.photonvision", - "artifactId": "photontargeting-cpp", - "version": "v2027.0.0-alpha-2", - "libName": "photontargeting", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxsystemcore", - "linuxx86-64", - "osxuniversal" - ] - } - ], - "javaDependencies": [ - { - "groupId": "org.photonvision", - "artifactId": "photonlib-java", - "version": "v2027.0.0-alpha-2" - }, - { - "groupId": "org.photonvision", - "artifactId": "photontargeting-java", - "version": "v2027.0.0-alpha-2" - } - ] -} \ No newline at end of file From ac785a6765c160cb92546e52fb137e3dbc4c303d Mon Sep 17 00:00:00 2001 From: Samson560915 Date: Wed, 28 Oct 2026 07:47:46 -0400 Subject: [PATCH 13/20] Added method to allow for getting of turret centric angle to allow view of the simulation robot spinning accurately in coordinationlayer. --- simgui-ds.json | 19 +++++-------- .../java/frc/robot/CoordinationLayer.java | 8 +++--- .../subsystems/turret/TurretSubsystem.java | 27 ++++++++++--------- 3 files changed, 24 insertions(+), 30 deletions(-) diff --git a/simgui-ds.json b/simgui-ds.json index ac74e387..71833d09 100644 --- a/simgui-ds.json +++ b/simgui-ds.json @@ -1,4 +1,5 @@ { + "Keyboard 0 Settings": {"window": {"visible": true}}, "keyboardJoysticks": [{ "axisConfig": [{ "decKey": 546, @@ -7,14 +8,15 @@ "decKey": 568, "incKey": 564 }, { - "decKey": 550, "decayRate": 0, - "incKey": 563, "keyRate": 0.01 + }, {}, { + "decKey": 556, + "incKey": 555 }], - "axisCount": 3, - "buttonCount": 4, - "buttonKeys": [571, 569, 548, 567], + "axisCount": 5, + "buttonCount": 18, + "buttonKeys": [571, 569, 548, 567, 563, 561, 552, 566, 554, 560, -1, -1, 557, 553, 565, 550, 559, 562], "povConfig": [{ "keyDown": 614, "keyDownLeft": 613, @@ -27,13 +29,6 @@ }], "povCount": 1 }, { - "axisConfig": [{ - "decKey": 555, - "incKey": 557 - }, { - "decKey": 554, - "incKey": 556 - }], "axisCount": 2, "buttonCount": 4, "buttonKeys": [558, 597, 599, 600], diff --git a/src/main/java/frc/robot/CoordinationLayer.java b/src/main/java/frc/robot/CoordinationLayer.java index 284c74af..73737fb9 100644 --- a/src/main/java/frc/robot/CoordinationLayer.java +++ b/src/main/java/frc/robot/CoordinationLayer.java @@ -1233,12 +1233,10 @@ private boolean shouldStowHoodBasedOnMovement(Drive drive, HoodSubsystem hood) { Translation2d turretLocation = new Pose3d(robotPose) .plus(JsonConstants.robotInfo.robotToShooter) .getTranslation() - .toTranslation2d(); - - //Angle turretAngle = turret.map(TurretSubsystem::getTurretAngleRobotRelative).orElse(Radians.of(1)); - + .toTranslation2d(); - double turretAngle = turret.map(turret -> turret.getGoalTurretHeading().getRadians()).orElse(0.0); + double turretAngle = turret.map(turret -> turret.getTurretCentricHeading().getRadians()).orElse(0.0); + //double turretAngle = turret.map(turret -> turret.getTurretAngleRobotRelative().in(Radians)).orElse(60.0); Rotation3d turretRotation = new Rotation3d(new Rotation2d(turretAngle)); diff --git a/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java b/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java index c6c101b2..ac90e13b 100644 --- a/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java +++ b/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java @@ -473,7 +473,7 @@ private void controlToTurretCentricPosition(Angle goalAngleTurretCentric) { } private void controlToTurretCentricPositionRaw(Angle goalAngleTurretCentric) { - Logger.recordOutput("Turret/GoalAngle", goalAngleTurretCentric); //TODO: figure out where this is logged + Logger.recordOutput("Turret/GoalAngle", goalAngleTurretCentric); Angle clampedGoalAngle; // With changes to normalize heading // if goalAngelTurretCentric is negative, set it to 360 + goalAngleTurretCentric Degrees @@ -504,7 +504,7 @@ private void controlToTurretCentricPositionRaw(Angle goalAngleTurretCentric) { Logger.recordOutput("Turret/ClampedGoalAngle", clampedGoalAngle); - if (!brakeForIntake()) { + if (!brakeForIntake()) { //TODO: Here is the issue with the problem of the mechanism not moving comment this out in SIM motor.controlToPositionExpoProfiled(clampedGoalAngle); } } @@ -539,18 +539,15 @@ private Angle applyGoalAngleOffset(Angle goalAngleTurretCentric) { return goalAngleTurretCentric.plus(getGoalAngleOffset(goalAngleTurretCentric)); } - private Rotation2d getAdjustedGoalTurretHeadingFieldCentric() { + private Rotation2d getAdjustedGoalTurretHeadingFieldCentric() { //TODO: Untested Rotation2d robotRelativeHeading = goalTurretHeading.minus(dependencies.robotHeading); - // Rotation2d turretRelativeHeading = - // AngleUtil.normalizeHeading( - // robotRelativeHeading.plus( - // new Rotation2d(JsonConstants.turretConstants.headingToTurretAngle))); - - // Angle adjustedTurretAngle = applyGoalAngleOffset(turretRelativeHeading.getMeasure()); - // return new Rotation2d( - // adjustedTurretAngle.minus(JsonConstants.turretConstants.headingToTurretAngle)) - // .plus(dependencies.robotHeading); - return new Rotation2d(); // TO BE REMOVED + Rotation2d turretRelativeHeading = robotRelativeHeading.plus(new Rotation2d(JsonConstants.turretConstants.headingToTurretAngle)); + + Angle adjustedTurretAngle = applyGoalAngleOffset(turretRelativeHeading.getMeasure()); + return new Rotation2d( + adjustedTurretAngle.minus(JsonConstants.turretConstants.headingToTurretAngle)) + .plus(dependencies.robotHeading); + //return new Rotation2d(); // TO BE REMOVED } /** @@ -608,6 +605,10 @@ public Rotation2d getGoalTurretHeading() { return goalTurretHeading; } + public Rotation2d getTurretCentricHeading() { + return goalTurretHeading.minus(dependencies.robotHeading); + } + /** * Calculates the current field centric turret heading, by converting turret heading to a * robot-centric heading and then adjusting for robot heading. From 63882383916e9fa12b594f53dd73ceb7ccd8ce3b Mon Sep 17 00:00:00 2001 From: Samson560915 Date: Wed, 28 Oct 2026 19:04:22 -0400 Subject: [PATCH 14/20] Added simgui-ds.json to .gitignore file and fixed comments in TurretSubsystem file. --- simgui-ds.json | 54 ------------------- .../subsystems/turret/TurretSubsystem.java | 2 +- 2 files changed, 1 insertion(+), 55 deletions(-) delete mode 100644 simgui-ds.json diff --git a/simgui-ds.json b/simgui-ds.json deleted file mode 100644 index 71833d09..00000000 --- a/simgui-ds.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "Keyboard 0 Settings": {"window": {"visible": true}}, - "keyboardJoysticks": [{ - "axisConfig": [{ - "decKey": 546, - "incKey": 549 - }, { - "decKey": 568, - "incKey": 564 - }, { - "decayRate": 0, - "keyRate": 0.01 - }, {}, { - "decKey": 556, - "incKey": 555 - }], - "axisCount": 5, - "buttonCount": 18, - "buttonKeys": [571, 569, 548, 567, 563, 561, 552, 566, 554, 560, -1, -1, 557, 553, 565, 550, 559, 562], - "povConfig": [{ - "keyDown": 614, - "keyDownLeft": 613, - "keyDownRight": 615, - "keyLeft": 616, - "keyRight": 618, - "keyUp": 620, - "keyUpLeft": 619, - "keyUpRight": 621 - }], - "povCount": 1 - }, { - "axisCount": 2, - "buttonCount": 4, - "buttonKeys": [558, 597, 599, 600], - "povCount": 0 - }, { - "axisConfig": [{ - "decKey": 513, - "incKey": 514 - }, { - "decKey": 515, - "incKey": 516 - }], - "axisCount": 2, - "buttonCount": 6, - "buttonKeys": [521, 519, 517, 522, 520, 518], - "povCount": 0 - }, { - "axisCount": 0, - "buttonCount": 0, - "povCount": 0 - }], - "robotJoysticks": [{"guid": "Keyboard0"}] - } diff --git a/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java b/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java index ac90e13b..e7da54d8 100644 --- a/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java +++ b/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java @@ -504,7 +504,7 @@ private void controlToTurretCentricPositionRaw(Angle goalAngleTurretCentric) { Logger.recordOutput("Turret/ClampedGoalAngle", clampedGoalAngle); - if (!brakeForIntake()) { //TODO: Here is the issue with the problem of the mechanism not moving comment this out in SIM + if (!brakeForIntake()) { //TODO: Here is the issue with the problem of the mechanism not moving comment this out in SIM although that doesn't work in SIM anyway motor.controlToPositionExpoProfiled(clampedGoalAngle); } } From db8b5345ffc20662e3ea82724ecb46350aaf7ce0 Mon Sep 17 00:00:00 2001 From: Samson560915 Date: Wed, 28 Oct 2026 19:05:27 -0400 Subject: [PATCH 15/20] Added simgui-ds.json to .gitignore and fixed comments in TurretSubsystem. --- .gitignore | 1 + .../java/frc/robot/subsystems/turret/TurretSubsystem.java | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 34cbaac1..e026a2eb 100644 --- a/.gitignore +++ b/.gitignore @@ -172,6 +172,7 @@ out/ networktables.json simgui.json *-window.json +simgui-ds.json # Simulation data log directory logs/ diff --git a/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java b/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java index e7da54d8..1108a136 100644 --- a/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java +++ b/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java @@ -476,7 +476,7 @@ private void controlToTurretCentricPositionRaw(Angle goalAngleTurretCentric) { Logger.recordOutput("Turret/GoalAngle", goalAngleTurretCentric); Angle clampedGoalAngle; // With changes to normalize heading - // if goalAngelTurretCentric is negative, set it to 360 + goalAngleTurretCentric Degrees + // if goalAngleTurretCentric is negative, set it to 360 + goalAngleTurretCentric Degrees if (goalAngleTurretCentric.lt(Degrees.of(0))) { goalAngleTurretCentric = Degrees.of(360).plus(goalAngleTurretCentric); @@ -504,7 +504,7 @@ private void controlToTurretCentricPositionRaw(Angle goalAngleTurretCentric) { Logger.recordOutput("Turret/ClampedGoalAngle", clampedGoalAngle); - if (!brakeForIntake()) { //TODO: Here is the issue with the problem of the mechanism not moving comment this out in SIM although that doesn't work in SIM anyway + if (!brakeForIntake()) { //Comment this if statement out to let the mechanism move in SIM motor.controlToPositionExpoProfiled(clampedGoalAngle); } } @@ -547,7 +547,6 @@ private Rotation2d getAdjustedGoalTurretHeadingFieldCentric() { //TODO: Untested return new Rotation2d( adjustedTurretAngle.minus(JsonConstants.turretConstants.headingToTurretAngle)) .plus(dependencies.robotHeading); - //return new Rotation2d(); // TO BE REMOVED } /** From aa79256fe2f0c68684e7494b60eead45cb57d9bd Mon Sep 17 00:00:00 2001 From: Samson560915 Date: Wed, 28 Oct 2026 19:27:38 -0400 Subject: [PATCH 16/20] Fix up final comments before merge. --- src/main/java/frc/robot/CoordinationLayer.java | 3 +-- src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/frc/robot/CoordinationLayer.java b/src/main/java/frc/robot/CoordinationLayer.java index 73737fb9..c2292743 100644 --- a/src/main/java/frc/robot/CoordinationLayer.java +++ b/src/main/java/frc/robot/CoordinationLayer.java @@ -1236,7 +1236,6 @@ private boolean shouldStowHoodBasedOnMovement(Drive drive, HoodSubsystem hood) { .toTranslation2d(); double turretAngle = turret.map(turret -> turret.getTurretCentricHeading().getRadians()).orElse(0.0); - //double turretAngle = turret.map(turret -> turret.getTurretAngleRobotRelative().in(Radians)).orElse(60.0); Rotation3d turretRotation = new Rotation3d(new Rotation2d(turretAngle)); @@ -1393,7 +1392,7 @@ private boolean runShotCalculatorWithDrive(Drive driveInstance) { turret.ifPresent( turret -> { turret.targetGoalHeading(shot.yaw()); - }); + }); hood.ifPresent( hood -> { diff --git a/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java b/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java index 1108a136..326363bf 100644 --- a/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java +++ b/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java @@ -539,7 +539,7 @@ private Angle applyGoalAngleOffset(Angle goalAngleTurretCentric) { return goalAngleTurretCentric.plus(getGoalAngleOffset(goalAngleTurretCentric)); } - private Rotation2d getAdjustedGoalTurretHeadingFieldCentric() { //TODO: Untested + public Rotation2d getAdjustedGoalTurretHeadingFieldCentric() { Rotation2d robotRelativeHeading = goalTurretHeading.minus(dependencies.robotHeading); Rotation2d turretRelativeHeading = robotRelativeHeading.plus(new Rotation2d(JsonConstants.turretConstants.headingToTurretAngle)); From f278141415ea01b68686799879a166fa0e48c5ee Mon Sep 17 00:00:00 2001 From: Samson560915 Date: Wed, 28 Oct 2026 19:41:34 -0400 Subject: [PATCH 17/20] Attempt to remove simgui-ds.json by commiting for update potentially? --- .gitignore | 1 - simgui-ds.json | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 simgui-ds.json diff --git a/.gitignore b/.gitignore index e026a2eb..34cbaac1 100644 --- a/.gitignore +++ b/.gitignore @@ -172,7 +172,6 @@ out/ networktables.json simgui.json *-window.json -simgui-ds.json # Simulation data log directory logs/ diff --git a/simgui-ds.json b/simgui-ds.json new file mode 100644 index 00000000..71833d09 --- /dev/null +++ b/simgui-ds.json @@ -0,0 +1,54 @@ +{ + "Keyboard 0 Settings": {"window": {"visible": true}}, + "keyboardJoysticks": [{ + "axisConfig": [{ + "decKey": 546, + "incKey": 549 + }, { + "decKey": 568, + "incKey": 564 + }, { + "decayRate": 0, + "keyRate": 0.01 + }, {}, { + "decKey": 556, + "incKey": 555 + }], + "axisCount": 5, + "buttonCount": 18, + "buttonKeys": [571, 569, 548, 567, 563, 561, 552, 566, 554, 560, -1, -1, 557, 553, 565, 550, 559, 562], + "povConfig": [{ + "keyDown": 614, + "keyDownLeft": 613, + "keyDownRight": 615, + "keyLeft": 616, + "keyRight": 618, + "keyUp": 620, + "keyUpLeft": 619, + "keyUpRight": 621 + }], + "povCount": 1 + }, { + "axisCount": 2, + "buttonCount": 4, + "buttonKeys": [558, 597, 599, 600], + "povCount": 0 + }, { + "axisConfig": [{ + "decKey": 513, + "incKey": 514 + }, { + "decKey": 515, + "incKey": 516 + }], + "axisCount": 2, + "buttonCount": 6, + "buttonKeys": [521, 519, 517, 522, 520, 518], + "povCount": 0 + }, { + "axisCount": 0, + "buttonCount": 0, + "povCount": 0 + }], + "robotJoysticks": [{"guid": "Keyboard0"}] + } From 4501505764c6646204fac07d84ff8b8cf92723a4 Mon Sep 17 00:00:00 2001 From: Samson560915 Date: Wed, 28 Oct 2026 19:43:04 -0400 Subject: [PATCH 18/20] git removed simgui-ds.json. --- simgui-ds.json | 54 -------------------------------------------------- 1 file changed, 54 deletions(-) delete mode 100644 simgui-ds.json diff --git a/simgui-ds.json b/simgui-ds.json deleted file mode 100644 index 71833d09..00000000 --- a/simgui-ds.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "Keyboard 0 Settings": {"window": {"visible": true}}, - "keyboardJoysticks": [{ - "axisConfig": [{ - "decKey": 546, - "incKey": 549 - }, { - "decKey": 568, - "incKey": 564 - }, { - "decayRate": 0, - "keyRate": 0.01 - }, {}, { - "decKey": 556, - "incKey": 555 - }], - "axisCount": 5, - "buttonCount": 18, - "buttonKeys": [571, 569, 548, 567, 563, 561, 552, 566, 554, 560, -1, -1, 557, 553, 565, 550, 559, 562], - "povConfig": [{ - "keyDown": 614, - "keyDownLeft": 613, - "keyDownRight": 615, - "keyLeft": 616, - "keyRight": 618, - "keyUp": 620, - "keyUpLeft": 619, - "keyUpRight": 621 - }], - "povCount": 1 - }, { - "axisCount": 2, - "buttonCount": 4, - "buttonKeys": [558, 597, 599, 600], - "povCount": 0 - }, { - "axisConfig": [{ - "decKey": 513, - "incKey": 514 - }, { - "decKey": 515, - "incKey": 516 - }], - "axisCount": 2, - "buttonCount": 6, - "buttonKeys": [521, 519, 517, 522, 520, 518], - "povCount": 0 - }, { - "axisCount": 0, - "buttonCount": 0, - "povCount": 0 - }], - "robotJoysticks": [{"guid": "Keyboard0"}] - } From ac1b442733f8e0c80ad24d840e365f7392feebd3 Mon Sep 17 00:00:00 2001 From: Samson560915 Date: Wed, 28 Oct 2026 19:44:43 -0400 Subject: [PATCH 19/20] added simgui-ds.json to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 34cbaac1..e026a2eb 100644 --- a/.gitignore +++ b/.gitignore @@ -172,6 +172,7 @@ out/ networktables.json simgui.json *-window.json +simgui-ds.json # Simulation data log directory logs/ From 3b6dc9d26798b203c4b58cffee0b79dd4faf12a7 Mon Sep 17 00:00:00 2001 From: Samson560915 Date: Mon, 2 Nov 2026 18:44:16 -0500 Subject: [PATCH 20/20] Added comments to public methods and privated a method as we no longer need it for testing. --- src/main/java/frc/robot/CoordinationLayer.java | 2 ++ .../frc/robot/subsystems/turret/TurretSubsystem.java | 11 +++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/frc/robot/CoordinationLayer.java b/src/main/java/frc/robot/CoordinationLayer.java index b435a3cf..8874bebe 100644 --- a/src/main/java/frc/robot/CoordinationLayer.java +++ b/src/main/java/frc/robot/CoordinationLayer.java @@ -1233,6 +1233,8 @@ private boolean shouldStowHoodBasedOnMovement(Drive drive, HoodSubsystem hood) { new Pose2d(movementEnd, robotPose.getRotation())); EnhancedLine2d movementLine = new EnhancedLine2d(movementStart, movementEnd); + // Log turret trajectory for debugging. + Translation2d turretLocation = new Pose3d(robotPose) .plus(JsonConstants.robotInfo.robotToShooter) .getTranslation() diff --git a/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java b/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java index b8edd8ed..c73ffe16 100644 --- a/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java +++ b/src/main/java/frc/robot/subsystems/turret/TurretSubsystem.java @@ -503,7 +503,8 @@ private void controlToTurretCentricPositionRaw(Angle goalAngleTurretCentric) { Logger.recordOutput("Turret/ClampedGoalAngle", clampedGoalAngle); - if (!brakeForIntake()) { //Comment this if statement out to let the mechanism move in SIM + if (!brakeForIntake()) //Comment this if statement out to let the mechanism move in SIM, leave what is inside the if statement. + { motor.controlToPositionExpoProfiled(clampedGoalAngle); } } @@ -538,7 +539,7 @@ private Angle applyGoalAngleOffset(Angle goalAngleTurretCentric) { return goalAngleTurretCentric.plus(getGoalAngleOffset(goalAngleTurretCentric)); } - public Rotation2d getAdjustedGoalTurretHeadingFieldCentric() { + private Rotation2d getAdjustedGoalTurretHeadingFieldCentric() { Rotation2d robotRelativeHeading = goalTurretHeading.minus(dependencies.robotHeading); Rotation2d turretRelativeHeading = robotRelativeHeading.plus(new Rotation2d(JsonConstants.turretConstants.headingToTurretAngle)); @@ -599,10 +600,16 @@ public void targetGoalHeading(Rotation2d goalHeading) { this.goalTurretHeading = goalHeading; } + /** + * @return A Rotation2d containing the field-centric goal heading of the turret. + */ public Rotation2d getGoalTurretHeading() { return goalTurretHeading; } + /** + * @return A Rotation2d containing the turret-centric goal heading of the turret. + */ public Rotation2d getTurretCentricHeading() { return goalTurretHeading.minus(dependencies.robotHeading); }