.
diff --git a/WPILib-License.md b/WPILib-License.md
index 645e542..e7cd597 100644
--- a/WPILib-License.md
+++ b/WPILib-License.md
@@ -1,24 +1,24 @@
-Copyright (c) 2009-2024 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.
-
-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
-WARRANTIES OF MERCHANTABILITY NONINFRINGEMENT AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FIRST OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+Copyright (c) 2009-2024 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.
+
+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
+WARRANTIES OF MERCHANTABILITY NONINFRINGEMENT AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FIRST OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/build.gradle b/build.gradle
index 327ca60..f230c5e 100755
--- a/build.gradle
+++ b/build.gradle
@@ -1,183 +1,183 @@
-plugins {
- id "java"
- id "edu.wpi.first.GradleRIO" version "2024.1.1"
- id "com.peterabeles.gversion" version "1.10"
- id "com.diffplug.spotless" version "6.12.0"
-}
-
-java {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
-
-def ROBOT_MAIN_CLASS = "frc.robot.Main"
-
-// Define my targets (RoboRIO) and artifacts (deployable files)
-// This is added by GradleRIO's backing project DeployUtils.
-deploy {
- targets {
- roborio(getTargetTypeClass('RoboRIO')) {
- // 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)
-
- 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')) {
- }
-
- // Static files artifact
- frcStaticFileDeploy(getArtifactTypeClass('FileTreeArtifact')) {
- files = project.fileTree('src/main/deploy')
- directory = '/home/lvuser/deploy'
- }
- }
- }
- }
-}
-
-def deployArtifact = deploy.targets.roborio.artifacts.frcJava
-
-// Set to true to use debug for JNI.
-wpi.java.debugJni = false
-
-// Set this to true to enable desktop support.
-def includeDesktopSupport = true
-
-// Configuration for AdvantageKit
-repositories {
- maven {
- url = uri("https://maven.pkg.github.com/Mechanical-Advantage/AdvantageKit")
- credentials {
- username = "Mechanical-Advantage-Bot"
- password = "\u0067\u0068\u0070\u005f\u006e\u0056\u0051\u006a\u0055\u004f\u004c\u0061\u0079\u0066\u006e\u0078\u006e\u0037\u0051\u0049\u0054\u0042\u0032\u004c\u004a\u006d\u0055\u0070\u0073\u0031\u006d\u0037\u004c\u005a\u0030\u0076\u0062\u0070\u0063\u0051"
- }
- }
- mavenLocal()
-}
-
-configurations.all {
- exclude group: "edu.wpi.first.wpilibj"
-}
-
-task(checkAkitInstall, dependsOn: "classes", type: JavaExec) {
- mainClass = "org.littletonrobotics.junction.CheckInstall"
- classpath = sourceSets.main.runtimeClasspath
-}
-compileJava.finalizedBy checkAkitInstall
-
-// Defining my dependencies. In this case, WPILib (+ friends), and vendor libraries.
-// Also defines JUnit 4.
-dependencies {
- 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)
-
- roborioRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.roborio)
- roborioRelease wpi.java.vendor.jniRelease(wpi.platforms.roborio)
-
- nativeDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.desktop)
- nativeDebug wpi.java.vendor.jniDebug(wpi.platforms.desktop)
- simulationDebug wpi.sim.enableDebug()
-
- nativeRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.desktop)
- nativeRelease wpi.java.vendor.jniRelease(wpi.platforms.desktop)
- simulationRelease wpi.sim.enableRelease()
-
- testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1'
- testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
-
- implementation 'gov.nist.math:jama:1.0.3'
-
- def akitJson = new groovy.json.JsonSlurper().parseText(new File(projectDir.getAbsolutePath() + "/vendordeps/AdvantageKit.json").text)
- annotationProcessor "org.littletonrobotics.akit.junction:junction-autolog:$akitJson.version"
-}
-
-test {
- useJUnitPlatform()
- systemProperty 'junit.jupiter.extensions.autodetection.enabled', 'true'
-}
-
-// Simulation configuration (e.g. environment variables).
-wpi.sim.addGui()
-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)
- duplicatesStrategy = DuplicatesStrategy.INCLUDE
-}
-
-// Configure jar and deploy tasks
-deployArtifact.jarTask = jar
-wpi.java.configureExecutableTasks(jar)
-wpi.java.configureTestTasks(test)
-
-// Configure string concat to always inline compile
-tasks.withType(JavaCompile) {
- options.compilerArgs.add '-XDstringConcat=inline'
-}
-
-// 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 = " "
-}
-
-// Spotless formatting
-project.compileJava.dependsOn(spotlessApply)
-spotless {
- java {
- target fileTree(".") {
- include "**/*.java"
- exclude "**/build/**", "**/build-*/**"
- }
- toggleOffOn()
- googleJavaFormat()
- removeUnusedImports()
- trimTrailingWhitespace()
- endWithNewline()
- }
- groovyGradle {
- target fileTree(".") {
- include "**/*.gradle"
- exclude "**/build/**", "**/build-*/**"
- }
- greclipse()
- indentWithSpaces(4)
- trimTrailingWhitespace()
- endWithNewline()
- }
- json {
- target fileTree(".") {
- include "**/*.json"
- exclude "**/build/**", "**/build-*/**"
- }
- gson().indentWithSpaces(2)
- }
- format "misc", {
- target fileTree(".") {
- include "**/*.md", "**/.gitignore"
- exclude "**/build/**", "**/build-*/**"
- }
- trimTrailingWhitespace()
- indentWithSpaces(2)
- endWithNewline()
- }
-}
+plugins {
+ id "java"
+ id "edu.wpi.first.GradleRIO" version "2024.3.1"
+ id "com.peterabeles.gversion" version "1.10"
+ id "com.diffplug.spotless" version "6.12.0"
+}
+
+java {
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
+}
+
+def ROBOT_MAIN_CLASS = "frc.robot.Main"
+
+// Define my targets (RoboRIO) and artifacts (deployable files)
+// This is added by GradleRIO's backing project DeployUtils.
+deploy {
+ targets {
+ roborio(getTargetTypeClass('RoboRIO')) {
+ // 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)
+
+ 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')) {
+ }
+
+ // Static files artifact
+ frcStaticFileDeploy(getArtifactTypeClass('FileTreeArtifact')) {
+ files = project.fileTree('src/main/deploy')
+ directory = '/home/lvuser/deploy'
+ }
+ }
+ }
+ }
+}
+
+def deployArtifact = deploy.targets.roborio.artifacts.frcJava
+
+// Set to true to use debug for JNI.
+wpi.java.debugJni = false
+
+// Set this to true to enable desktop support.
+def includeDesktopSupport = true
+
+// Configuration for AdvantageKit
+repositories {
+ maven {
+ url = uri("https://maven.pkg.github.com/Mechanical-Advantage/AdvantageKit")
+ credentials {
+ username = "Mechanical-Advantage-Bot"
+ password = "\u0067\u0068\u0070\u005f\u006e\u0056\u0051\u006a\u0055\u004f\u004c\u0061\u0079\u0066\u006e\u0078\u006e\u0037\u0051\u0049\u0054\u0042\u0032\u004c\u004a\u006d\u0055\u0070\u0073\u0031\u006d\u0037\u004c\u005a\u0030\u0076\u0062\u0070\u0063\u0051"
+ }
+ }
+ mavenLocal()
+}
+
+configurations.all {
+ exclude group: "edu.wpi.first.wpilibj"
+}
+
+task(checkAkitInstall, dependsOn: "classes", type: JavaExec) {
+ mainClass = "org.littletonrobotics.junction.CheckInstall"
+ classpath = sourceSets.main.runtimeClasspath
+}
+compileJava.finalizedBy checkAkitInstall
+
+// Defining my dependencies. In this case, WPILib (+ friends), and vendor libraries.
+// Also defines JUnit 4.
+dependencies {
+ 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)
+
+ roborioRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.roborio)
+ roborioRelease wpi.java.vendor.jniRelease(wpi.platforms.roborio)
+
+ nativeDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.desktop)
+ nativeDebug wpi.java.vendor.jniDebug(wpi.platforms.desktop)
+ simulationDebug wpi.sim.enableDebug()
+
+ nativeRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.desktop)
+ nativeRelease wpi.java.vendor.jniRelease(wpi.platforms.desktop)
+ simulationRelease wpi.sim.enableRelease()
+
+ testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1'
+ testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
+
+ implementation 'gov.nist.math:jama:1.0.3'
+
+ def akitJson = new groovy.json.JsonSlurper().parseText(new File(projectDir.getAbsolutePath() + "/vendordeps/AdvantageKit.json").text)
+ annotationProcessor "org.littletonrobotics.akit.junction:junction-autolog:$akitJson.version"
+}
+
+test {
+ useJUnitPlatform()
+ systemProperty 'junit.jupiter.extensions.autodetection.enabled', 'true'
+}
+
+// Simulation configuration (e.g. environment variables).
+wpi.sim.addGui()
+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)
+ duplicatesStrategy = DuplicatesStrategy.INCLUDE
+}
+
+// Configure jar and deploy tasks
+deployArtifact.jarTask = jar
+wpi.java.configureExecutableTasks(jar)
+wpi.java.configureTestTasks(test)
+
+// Configure string concat to always inline compile
+tasks.withType(JavaCompile) {
+ options.compilerArgs.add '-XDstringConcat=inline'
+}
+
+// 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 = " "
+}
+
+// Spotless formatting
+project.compileJava.dependsOn(spotlessApply)
+spotless {
+ java {
+ target fileTree(".") {
+ include "**/*.java"
+ exclude "**/build/**", "**/build-*/**"
+ }
+ toggleOffOn()
+ googleJavaFormat()
+ removeUnusedImports()
+ trimTrailingWhitespace()
+ endWithNewline()
+ }
+ groovyGradle {
+ target fileTree(".") {
+ include "**/*.gradle"
+ exclude "**/build/**", "**/build-*/**"
+ }
+ greclipse()
+ indentWithSpaces(4)
+ trimTrailingWhitespace()
+ endWithNewline()
+ }
+ json {
+ target fileTree(".") {
+ include "**/*.json"
+ exclude "**/build/**", "**/build-*/**"
+ }
+ gson().indentWithSpaces(2)
+ }
+ format "misc", {
+ target fileTree(".") {
+ include "**/*.md", "**/.gitignore"
+ exclude "**/build/**", "**/build-*/**"
+ }
+ trimTrailingWhitespace()
+ indentWithSpaces(2)
+ endWithNewline()
+ }
+}
diff --git a/settings.gradle b/settings.gradle
index d94f73c..3e30f84 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,30 +1,30 @@
-import org.gradle.internal.os.OperatingSystem
-
-pluginManagement {
- repositories {
- mavenLocal()
- gradlePluginPortal()
- String frcYear = '2024'
- File frcHome
- 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)
- } else {
- def userFolder = System.getProperty("user.home")
- def homeRoot = new File(userFolder, "wpilib")
- frcHome = new File(homeRoot, frcYear)
- }
- def frcHomeMaven = new File(frcHome, 'maven')
- maven {
- name 'frcHome'
- url frcHomeMaven
- }
- }
-}
-
-Properties props = System.getProperties();
-props.setProperty("org.gradle.internal.native.headers.unresolved.dependencies.ignore", "true");
+import org.gradle.internal.os.OperatingSystem
+
+pluginManagement {
+ repositories {
+ mavenLocal()
+ gradlePluginPortal()
+ String frcYear = '2024'
+ File frcHome
+ 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)
+ } else {
+ def userFolder = System.getProperty("user.home")
+ def homeRoot = new File(userFolder, "wpilib")
+ frcHome = new File(homeRoot, frcYear)
+ }
+ def frcHomeMaven = new File(frcHome, 'maven')
+ maven {
+ name 'frcHome'
+ url frcHomeMaven
+ }
+ }
+}
+
+Properties props = System.getProperties();
+props.setProperty("org.gradle.internal.native.headers.unresolved.dependencies.ignore", "true");
diff --git a/src/main/deploy/pathplanner/navgrid.json b/src/main/deploy/pathplanner/navgrid.json
index 690f5db..f7bbeef 100644
--- a/src/main/deploy/pathplanner/navgrid.json
+++ b/src/main/deploy/pathplanner/navgrid.json
@@ -1,1633 +1,1633 @@
-{
- "field_size": {
- "x": 16.54,
- "y": 8.21
- },
- "nodeSizeMeters": 0.3,
- "grid": [
- [
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true
- ],
- [
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true
- ],
- [
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true
- ],
- [
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true
- ],
- [
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true
- ],
- [
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true
- ],
- [
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true
- ],
- [
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true
- ],
- [
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true
- ],
- [
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true
- ],
- [
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true
- ],
- [
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true
- ],
- [
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true
- ],
- [
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true
- ],
- [
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true
- ],
- [
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true
- ],
- [
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true
- ],
- [
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true
- ],
- [
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true
- ],
- [
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true
- ],
- [
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true
- ],
- [
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true
- ],
- [
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true
- ],
- [
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true
- ],
- [
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true
- ],
- [
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true
- ],
- [
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true
- ],
- [
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true
- ]
- ]
-}
+{
+ "field_size": {
+ "x": 16.54,
+ "y": 8.21
+ },
+ "nodeSizeMeters": 0.3,
+ "grid": [
+ [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ]
+ ]
+}
diff --git a/src/main/java/frc/robot/Constants.java b/src/main/java/frc/robot/Constants.java
index 18e9321..293bf77 100644
--- a/src/main/java/frc/robot/Constants.java
+++ b/src/main/java/frc/robot/Constants.java
@@ -1,79 +1,79 @@
-// Copyright 2021-2024 FRC 6328
-// http://github.com/Mechanical-Advantage
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// version 3 as published by the Free Software Foundation or
-// available in the root directory of this project.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-package frc.robot;
-
-import edu.wpi.first.math.geometry.Rotation2d;
-
-/**
- * The Constants class provides a convenient place for teams to hold robot-wide numerical or boolean
- * constants. This class should not be used for any other purpose. All constants should be declared
- * globally (i.e. public static). Do not put anything functional in this class.
- *
- * It is advised to statically import this class (or one of its inner classes) wherever the
- * constants are needed, to reduce verbosity.
- */
-public final class Constants {
- public static final Mode currentMode = Mode.SIM;
-
- public static enum Mode {
- /** Running on a real robot. */
- REAL,
- /** Running a physics simulator. */
- SIM,
- /** Replaying from a log file. */
- REPLAY
- }
-
- public static class DriveConstants {
- // Front Left, Front Right, Back Left, Back Right
- // IN DEGREES
- public static final double[] moduleAngles = new double[] {0, 0, 0, 0};
-
- public static final int[] turnCanIds = new int[] {1, 4, 7, 10};
- public static final int[] driveCanIds = new int[] {0, 3, 6, 9};
- public static final int[] canCoderIds = new int[] {2, 5, 8, 11};
- }
-
- public static class IntakeConstants {
- public static final int intakeCANId = 12;
-
- public static final double intakeOnPower = 0.1;
- }
-
- public static class PivotConstants {
- public static final int pivotCANId = 13;
-
- // 80 falcon rotations = 1 pivot rotation
- // 5:1 planetary + 5:1 planetary + 5:1 planetary + 48:15 chain
- public static final int pivotGearRatio = 400;
-
- // the mechanically stopped beginning of the pivot is at a negative angle from the ground
- // 0 degrees is parallel to the ground and facing the same direction as the back of the robot
- public static Rotation2d pivotStart = Rotation2d.fromDegrees(-8.265688);
- public static Rotation2d pivotEnd = Rotation2d.fromDegrees(129.056487);
- // less than this angle, we won't be able to shoot a note
- public static Rotation2d minShootingAngle = Rotation2d.fromDegrees(25);
-
- public static final double p = 0.05, i = 0, d = 0;
- }
-
- public static class ShooterConstants {
- public static final int conveyorCANId = 14;
- public static final int topShooterCANId = 15;
- public static final int bottomShooterCANId = 16;
-
- public static final double shootingPower = 0.5;
- public static final double conveyorPower = 0.2;
- }
-}
+// Copyright 2021-2024 FRC 6328
+// http://github.com/Mechanical-Advantage
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 3 as published by the Free Software Foundation or
+// available in the root directory of this project.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+package frc.robot;
+
+import edu.wpi.first.math.geometry.Rotation2d;
+
+/**
+ * The Constants class provides a convenient place for teams to hold robot-wide numerical or boolean
+ * constants. This class should not be used for any other purpose. All constants should be declared
+ * globally (i.e. public static). Do not put anything functional in this class.
+ *
+ *
It is advised to statically import this class (or one of its inner classes) wherever the
+ * constants are needed, to reduce verbosity.
+ */
+public final class Constants {
+ public static final Mode currentMode = Mode.SIM;
+
+ public static enum Mode {
+ /** Running on a real robot. */
+ REAL,
+ /** Running a physics simulator. */
+ SIM,
+ /** Replaying from a log file. */
+ REPLAY
+ }
+
+ public static class DriveConstants {
+ // Front Left, Front Right, Back Left, Back Right
+ // IN DEGREES
+ public static final double[] moduleAngles = new double[] {0, 0, 0, 0};
+
+ public static final int[] turnCanIds = new int[] {1, 4, 7, 10};
+ public static final int[] driveCanIds = new int[] {0, 3, 6, 9};
+ public static final int[] canCoderIds = new int[] {2, 5, 8, 11};
+ }
+
+ public static class IntakeConstants {
+ public static final int intakeCANId = 12;
+
+ public static final double intakeOnPower = 0.1;
+ }
+
+ public static class PivotConstants {
+ public static final int pivotCANId = 13;
+
+ // 80 falcon rotations = 1 pivot rotation
+ // 5:1 planetary + 5:1 planetary + 5:1 planetary + 48:15 chain
+ public static final int pivotGearRatio = 400;
+
+ // the mechanically stopped beginning of the pivot is at a negative angle from the ground
+ // 0 degrees is parallel to the ground and facing the same direction as the back of the robot
+ public static Rotation2d pivotStart = Rotation2d.fromDegrees(-8.265688);
+ public static Rotation2d pivotEnd = Rotation2d.fromDegrees(129.056487);
+ // less than this angle, we won't be able to shoot a note
+ public static Rotation2d minShootingAngle = Rotation2d.fromDegrees(25);
+
+ public static final double p = 0.05, i = 0, d = 0;
+ }
+
+ public static class ShooterConstants {
+ public static final int conveyorCANId = 14;
+ public static final int topShooterCANId = 15;
+ public static final int bottomShooterCANId = 16;
+
+ public static final double shootingPower = 0.5;
+ public static final double conveyorPower = 0.2;
+ }
+}
diff --git a/src/main/java/frc/robot/Main.java b/src/main/java/frc/robot/Main.java
index e8af1c1..c3752a6 100644
--- a/src/main/java/frc/robot/Main.java
+++ b/src/main/java/frc/robot/Main.java
@@ -1,34 +1,34 @@
-// Copyright 2021-2024 FRC 6328
-// http://github.com/Mechanical-Advantage
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// version 3 as published by the Free Software Foundation or
-// available in the root directory of this project.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-package frc.robot;
-
-import edu.wpi.first.wpilibj.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(Robot::new);
- }
-}
+// Copyright 2021-2024 FRC 6328
+// http://github.com/Mechanical-Advantage
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 3 as published by the Free Software Foundation or
+// available in the root directory of this project.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+package frc.robot;
+
+import edu.wpi.first.wpilibj.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(Robot::new);
+ }
+}
diff --git a/src/main/java/frc/robot/Robot.java b/src/main/java/frc/robot/Robot.java
index ea47d35..f326532 100644
--- a/src/main/java/frc/robot/Robot.java
+++ b/src/main/java/frc/robot/Robot.java
@@ -1,160 +1,160 @@
-// Copyright 2021-2024 FRC 6328
-// http://github.com/Mechanical-Advantage
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// version 3 as published by the Free Software Foundation or
-// available in the root directory of this project.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-package frc.robot;
-
-import edu.wpi.first.wpilibj2.command.Command;
-import edu.wpi.first.wpilibj2.command.CommandScheduler;
-import org.littletonrobotics.junction.LogFileUtil;
-import org.littletonrobotics.junction.LoggedRobot;
-import org.littletonrobotics.junction.Logger;
-import org.littletonrobotics.junction.networktables.NT4Publisher;
-import org.littletonrobotics.junction.wpilog.WPILOGReader;
-import org.littletonrobotics.junction.wpilog.WPILOGWriter;
-
-/**
- * The VM is configured to automatically run this class, and to call the functions corresponding to
- * each mode, as described in the TimedRobot documentation. If you change the name of this class or
- * the package after creating this project, you must also update the build.gradle file in the
- * project.
- */
-public class Robot extends LoggedRobot {
- private Command autonomousCommand;
- private RobotContainer robotContainer;
-
- /**
- * This function is run when the robot is first started up and should be used for any
- * initialization code.
- */
- @Override
- public void robotInit() {
- // Record metadata
- Logger.recordMetadata("ProjectName", BuildConstants.MAVEN_NAME);
- Logger.recordMetadata("BuildDate", BuildConstants.BUILD_DATE);
- Logger.recordMetadata("GitSHA", BuildConstants.GIT_SHA);
- Logger.recordMetadata("GitDate", BuildConstants.GIT_DATE);
- Logger.recordMetadata("GitBranch", BuildConstants.GIT_BRANCH);
- switch (BuildConstants.DIRTY) {
- case 0:
- Logger.recordMetadata("GitDirty", "All changes committed");
- break;
- case 1:
- Logger.recordMetadata("GitDirty", "Uncomitted changes");
- break;
- default:
- Logger.recordMetadata("GitDirty", "Unknown");
- break;
- }
-
- // Set up data receivers & replay source
- switch (Constants.currentMode) {
- case REAL:
- // Running on a real robot, log to a USB stick ("/U/logs")
- Logger.addDataReceiver(new WPILOGWriter());
- Logger.addDataReceiver(new NT4Publisher());
- break;
-
- case SIM:
- // Running a physics simulator, log to NT
- Logger.addDataReceiver(new NT4Publisher());
- break;
-
- case REPLAY:
- // Replaying a log, set up replay source
- setUseTiming(false); // Run as fast as possible
- String logPath = LogFileUtil.findReplayLog();
- Logger.setReplaySource(new WPILOGReader(logPath));
- Logger.addDataReceiver(new WPILOGWriter(LogFileUtil.addPathSuffix(logPath, "_sim")));
- break;
- }
-
- // See http://bit.ly/3YIzFZ6 for more information on timestamps in AdvantageKit.
- // Logger.disableDeterministicTimestamps()
-
- // Start AdvantageKit logger
- Logger.start();
-
- // Instantiate our RobotContainer. This will perform all our button bindings,
- // and put our autonomous chooser on the dashboard.
- robotContainer = new RobotContainer();
- }
-
- /** This function is called periodically during all modes. */
- @Override
- public void robotPeriodic() {
- // Runs the Scheduler. This is responsible for polling buttons, adding
- // newly-scheduled commands, running already-scheduled commands, removing
- // finished or interrupted commands, and running subsystem periodic() methods.
- // This must be called from the robot's periodic block in order for anything in
- // the Command-based framework to work.
- CommandScheduler.getInstance().run();
- }
-
- /** This function is called once when the robot is disabled. */
- @Override
- public void disabledInit() {}
-
- /** This function is called periodically when disabled. */
- @Override
- public void disabledPeriodic() {}
-
- /** This autonomous runs the autonomous command selected by your {@link RobotContainer} class. */
- @Override
- public void autonomousInit() {
- autonomousCommand = robotContainer.getAutonomousCommand();
-
- // schedule the autonomous command (example)
- if (autonomousCommand != null) {
- autonomousCommand.schedule();
- }
- }
-
- /** This function is called periodically during autonomous. */
- @Override
- public void autonomousPeriodic() {}
-
- /** This function is called once when teleop is enabled. */
- @Override
- public void teleopInit() {
- // This makes sure that the autonomous stops running when
- // teleop starts running. If you want the autonomous to
- // continue until interrupted by another command, remove
- // this line or comment it out.
- if (autonomousCommand != null) {
- autonomousCommand.cancel();
- }
- }
-
- /** This function is called periodically during operator control. */
- @Override
- public void teleopPeriodic() {}
-
- /** This function is called once when test mode is enabled. */
- @Override
- public void testInit() {
- // 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() {}
-
- /** This function is called once when the robot is first started up. */
- @Override
- public void simulationInit() {}
-
- /** This function is called periodically whilst in simulation. */
- @Override
- public void simulationPeriodic() {}
-}
+// Copyright 2021-2024 FRC 6328
+// http://github.com/Mechanical-Advantage
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 3 as published by the Free Software Foundation or
+// available in the root directory of this project.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+package frc.robot;
+
+import edu.wpi.first.wpilibj2.command.Command;
+import edu.wpi.first.wpilibj2.command.CommandScheduler;
+import org.littletonrobotics.junction.LogFileUtil;
+import org.littletonrobotics.junction.LoggedRobot;
+import org.littletonrobotics.junction.Logger;
+import org.littletonrobotics.junction.networktables.NT4Publisher;
+import org.littletonrobotics.junction.wpilog.WPILOGReader;
+import org.littletonrobotics.junction.wpilog.WPILOGWriter;
+
+/**
+ * The VM is configured to automatically run this class, and to call the functions corresponding to
+ * each mode, as described in the TimedRobot documentation. If you change the name of this class or
+ * the package after creating this project, you must also update the build.gradle file in the
+ * project.
+ */
+public class Robot extends LoggedRobot {
+ private Command autonomousCommand;
+ private RobotContainer robotContainer;
+
+ /**
+ * This function is run when the robot is first started up and should be used for any
+ * initialization code.
+ */
+ @Override
+ public void robotInit() {
+ // Record metadata
+ Logger.recordMetadata("ProjectName", BuildConstants.MAVEN_NAME);
+ Logger.recordMetadata("BuildDate", BuildConstants.BUILD_DATE);
+ Logger.recordMetadata("GitSHA", BuildConstants.GIT_SHA);
+ Logger.recordMetadata("GitDate", BuildConstants.GIT_DATE);
+ Logger.recordMetadata("GitBranch", BuildConstants.GIT_BRANCH);
+ switch (BuildConstants.DIRTY) {
+ case 0:
+ Logger.recordMetadata("GitDirty", "All changes committed");
+ break;
+ case 1:
+ Logger.recordMetadata("GitDirty", "Uncomitted changes");
+ break;
+ default:
+ Logger.recordMetadata("GitDirty", "Unknown");
+ break;
+ }
+
+ // Set up data receivers & replay source
+ switch (Constants.currentMode) {
+ case REAL:
+ // Running on a real robot, log to a USB stick ("/U/logs")
+ Logger.addDataReceiver(new WPILOGWriter());
+ Logger.addDataReceiver(new NT4Publisher());
+ break;
+
+ case SIM:
+ // Running a physics simulator, log to NT
+ Logger.addDataReceiver(new NT4Publisher());
+ break;
+
+ case REPLAY:
+ // Replaying a log, set up replay source
+ setUseTiming(false); // Run as fast as possible
+ String logPath = LogFileUtil.findReplayLog();
+ Logger.setReplaySource(new WPILOGReader(logPath));
+ Logger.addDataReceiver(new WPILOGWriter(LogFileUtil.addPathSuffix(logPath, "_sim")));
+ break;
+ }
+
+ // See http://bit.ly/3YIzFZ6 for more information on timestamps in AdvantageKit.
+ // Logger.disableDeterministicTimestamps()
+
+ // Start AdvantageKit logger
+ Logger.start();
+
+ // Instantiate our RobotContainer. This will perform all our button bindings,
+ // and put our autonomous chooser on the dashboard.
+ robotContainer = new RobotContainer();
+ }
+
+ /** This function is called periodically during all modes. */
+ @Override
+ public void robotPeriodic() {
+ // Runs the Scheduler. This is responsible for polling buttons, adding
+ // newly-scheduled commands, running already-scheduled commands, removing
+ // finished or interrupted commands, and running subsystem periodic() methods.
+ // This must be called from the robot's periodic block in order for anything in
+ // the Command-based framework to work.
+ CommandScheduler.getInstance().run();
+ }
+
+ /** This function is called once when the robot is disabled. */
+ @Override
+ public void disabledInit() {}
+
+ /** This function is called periodically when disabled. */
+ @Override
+ public void disabledPeriodic() {}
+
+ /** This autonomous runs the autonomous command selected by your {@link RobotContainer} class. */
+ @Override
+ public void autonomousInit() {
+ autonomousCommand = robotContainer.getAutonomousCommand();
+
+ // schedule the autonomous command (example)
+ if (autonomousCommand != null) {
+ autonomousCommand.schedule();
+ }
+ }
+
+ /** This function is called periodically during autonomous. */
+ @Override
+ public void autonomousPeriodic() {}
+
+ /** This function is called once when teleop is enabled. */
+ @Override
+ public void teleopInit() {
+ // This makes sure that the autonomous stops running when
+ // teleop starts running. If you want the autonomous to
+ // continue until interrupted by another command, remove
+ // this line or comment it out.
+ if (autonomousCommand != null) {
+ autonomousCommand.cancel();
+ }
+ }
+
+ /** This function is called periodically during operator control. */
+ @Override
+ public void teleopPeriodic() {}
+
+ /** This function is called once when test mode is enabled. */
+ @Override
+ public void testInit() {
+ // 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() {}
+
+ /** This function is called once when the robot is first started up. */
+ @Override
+ public void simulationInit() {}
+
+ /** This function is called periodically whilst in simulation. */
+ @Override
+ public void simulationPeriodic() {}
+}
diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java
index eebe1aa..3b24b06 100644
--- a/src/main/java/frc/robot/RobotContainer.java
+++ b/src/main/java/frc/robot/RobotContainer.java
@@ -1,160 +1,160 @@
-// Copyright 2021-2024 FRC 6328
-// http://github.com/Mechanical-Advantage
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// version 3 as published by the Free Software Foundation or
-// available in the root directory of this project.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-package frc.robot;
-
-import com.pathplanner.lib.auto.AutoBuilder;
-import edu.wpi.first.math.geometry.Pose2d;
-import edu.wpi.first.math.geometry.Rotation2d;
-import edu.wpi.first.wpilibj.GenericHID;
-import edu.wpi.first.wpilibj.XboxController;
-import edu.wpi.first.wpilibj2.command.Command;
-import edu.wpi.first.wpilibj2.command.Commands;
-import edu.wpi.first.wpilibj2.command.button.CommandXboxController;
-import frc.robot.commands.DriveCommands;
-import frc.robot.commands.FeedForwardCharacterization;
-import frc.robot.commands.PivotCommands;
-import frc.robot.subsystems.drive.*;
-import frc.robot.subsystems.intake.*;
-import frc.robot.subsystems.pivot.*;
-import frc.robot.subsystems.shooter.*;
-import org.littletonrobotics.junction.networktables.LoggedDashboardChooser;
-
-/**
- * This class is where the bulk of the robot should be declared. Since Command-based is a
- * "declarative" paradigm, very little robot logic should actually be handled in the {@link Robot}
- * periodic methods (other than the scheduler calls). Instead, the structure of the robot (including
- * subsystems, commands, and button mappings) should be declared here.
- */
-public class RobotContainer {
- // Subsystems
- private final Drive drive;
- private final Intake intake;
- private final Pivot pivot;
- private final Shooter shooter;
-
- // Controller
- private final CommandXboxController driver = new CommandXboxController(0);
- private final CommandXboxController operator = new CommandXboxController(1);
-
- // Dashboard inputs
- private final LoggedDashboardChooser autoChooser;
-
- /** The container for the robot. Contains subsystems, OI devices, and commands. */
- public RobotContainer() {
- switch (Constants.currentMode) {
- case REAL:
- drive =
- new Drive(
- new GyroIOPigeon2(true),
- new ModuleIOTalonFX(0),
- new ModuleIOTalonFX(1),
- new ModuleIOTalonFX(2),
- new ModuleIOTalonFX(3));
-
- intake = new Intake(new IntakeIOReal());
- pivot = new Pivot(new PivotIOReal());
- shooter = new Shooter(new ShooterIOReal());
-
- break;
-
- case SIM:
- // Sim robot, instantiate physics sim IO implementations
- drive =
- new Drive(
- new GyroIO() {},
- new ModuleIOSim(),
- new ModuleIOSim(),
- new ModuleIOSim(),
- new ModuleIOSim());
-
- intake = new Intake(new IntakeIOSim());
- pivot = new Pivot(new PivotIOSim());
- shooter = new Shooter(new ShooterIOSim());
-
- break;
-
- default:
- // Replayed robot, disable IO implementations
- drive =
- new Drive(
- new GyroIO() {},
- new ModuleIO() {},
- new ModuleIO() {},
- new ModuleIO() {},
- new ModuleIO() {});
-
- intake = new Intake(new IntakeIO() {});
- pivot = new Pivot(new PivotIO() {});
- shooter = new Shooter(new ShooterIO() {});
-
- break;
- }
-
- // Set up auto routines
- autoChooser = new LoggedDashboardChooser<>("Auto Choices", AutoBuilder.buildAutoChooser());
-
- // Set up feedforward characterization
- autoChooser.addOption(
- "Drive FF Characterization",
- new FeedForwardCharacterization(
- drive, drive::runCharacterizationVolts, drive::getCharacterizationVelocity));
-
- // Configure the button bindings
- configureButtonBindings();
- }
-
- /**
- * 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}.
- */
- private void configureButtonBindings() {
- drive.setDefaultCommand(
- DriveCommands.joystickDrive(
- drive, () -> -driver.getLeftY(), () -> -driver.getLeftX(), () -> -driver.getRightX()));
-
- driver.x().onTrue(Commands.runOnce(drive::stopWithX, drive));
-
- driver
- .b()
- .onTrue(
- Commands.runOnce(
- () ->
- drive.setPose(
- new Pose2d(drive.getPose().getTranslation(), new Rotation2d())),
- drive)
- .ignoringDisable(true));
-
- operator.a().toggleOnTrue(intake.onCommand());
- operator.b().toggleOnTrue(intake.offCommand());
- operator.rightBumper().toggleOnTrue(shooter.shootersOnCommand());
- operator.leftBumper().toggleOnTrue(shooter.shootersOffCommand());
- operator.x().toggleOnTrue(shooter.conveyorOnCommand());
- operator.y().toggleOnTrue(shooter.conveyorOffCommand());
-
- pivot.setDefaultCommand(
- PivotCommands.basicOperatorControl(
- pivot, () -> operator.getRightX() - operator.getLeftX()));
- }
-
- /**
- * Use this to pass the autonomous command to the main {@link Robot} class.
- *
- * @return the command to run in autonomous
- */
- public Command getAutonomousCommand() {
- return autoChooser.get();
- }
-}
+// Copyright 2021-2024 FRC 6328
+// http://github.com/Mechanical-Advantage
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 3 as published by the Free Software Foundation or
+// available in the root directory of this project.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+package frc.robot;
+
+import com.pathplanner.lib.auto.AutoBuilder;
+import edu.wpi.first.math.geometry.Pose2d;
+import edu.wpi.first.math.geometry.Rotation2d;
+import edu.wpi.first.wpilibj.GenericHID;
+import edu.wpi.first.wpilibj.XboxController;
+import edu.wpi.first.wpilibj2.command.Command;
+import edu.wpi.first.wpilibj2.command.Commands;
+import edu.wpi.first.wpilibj2.command.button.CommandXboxController;
+import frc.robot.commands.DriveCommands;
+import frc.robot.commands.FeedForwardCharacterization;
+import frc.robot.commands.PivotCommands;
+import frc.robot.subsystems.drive.*;
+import frc.robot.subsystems.intake.*;
+import frc.robot.subsystems.pivot.*;
+import frc.robot.subsystems.shooter.*;
+import org.littletonrobotics.junction.networktables.LoggedDashboardChooser;
+
+/**
+ * This class is where the bulk of the robot should be declared. Since Command-based is a
+ * "declarative" paradigm, very little robot logic should actually be handled in the {@link Robot}
+ * periodic methods (other than the scheduler calls). Instead, the structure of the robot (including
+ * subsystems, commands, and button mappings) should be declared here.
+ */
+public class RobotContainer {
+ // Subsystems
+ private final Drive drive;
+ private final Intake intake;
+ private final Pivot pivot;
+ private final Shooter shooter;
+
+ // Controller
+ private final CommandXboxController driver = new CommandXboxController(0);
+ private final CommandXboxController operator = new CommandXboxController(1);
+
+ // Dashboard inputs
+ private final LoggedDashboardChooser autoChooser;
+
+ /** The container for the robot. Contains subsystems, OI devices, and commands. */
+ public RobotContainer() {
+ switch (Constants.currentMode) {
+ case REAL:
+ drive =
+ new Drive(
+ new GyroIOPigeon2(true),
+ new ModuleIOTalonFX(0),
+ new ModuleIOTalonFX(1),
+ new ModuleIOTalonFX(2),
+ new ModuleIOTalonFX(3));
+
+ intake = new Intake(new IntakeIOReal());
+ pivot = new Pivot(new PivotIOReal());
+ shooter = new Shooter(new ShooterIOReal());
+
+ break;
+
+ case SIM:
+ // Sim robot, instantiate physics sim IO implementations
+ drive =
+ new Drive(
+ new GyroIO() {},
+ new ModuleIOSim(),
+ new ModuleIOSim(),
+ new ModuleIOSim(),
+ new ModuleIOSim());
+
+ intake = new Intake(new IntakeIOSim());
+ pivot = new Pivot(new PivotIOSim());
+ shooter = new Shooter(new ShooterIOSim());
+
+ break;
+
+ default:
+ // Replayed robot, disable IO implementations
+ drive =
+ new Drive(
+ new GyroIO() {},
+ new ModuleIO() {},
+ new ModuleIO() {},
+ new ModuleIO() {},
+ new ModuleIO() {});
+
+ intake = new Intake(new IntakeIO() {});
+ pivot = new Pivot(new PivotIO() {});
+ shooter = new Shooter(new ShooterIO() {});
+
+ break;
+ }
+
+ // Set up auto routines
+ autoChooser = new LoggedDashboardChooser<>("Auto Choices", AutoBuilder.buildAutoChooser());
+
+ // Set up feedforward characterization
+ autoChooser.addOption(
+ "Drive FF Characterization",
+ new FeedForwardCharacterization(
+ drive, drive::runCharacterizationVolts, drive::getCharacterizationVelocity));
+
+ // Configure the button bindings
+ configureButtonBindings();
+ }
+
+ /**
+ * 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}.
+ */
+ private void configureButtonBindings() {
+ drive.setDefaultCommand(
+ DriveCommands.joystickDrive(
+ drive, () -> -driver.getLeftY(), () -> -driver.getLeftX(), () -> -driver.getRightX()));
+
+ driver.x().onTrue(Commands.runOnce(drive::stopWithX, drive));
+
+ driver
+ .b()
+ .onTrue(
+ Commands.runOnce(
+ () ->
+ drive.setPose(
+ new Pose2d(drive.getPose().getTranslation(), new Rotation2d())),
+ drive)
+ .ignoringDisable(true));
+
+ operator.a().toggleOnTrue(intake.onCommand());
+ operator.b().toggleOnTrue(intake.offCommand());
+ operator.rightBumper().toggleOnTrue(shooter.shootersOnCommand());
+ operator.leftBumper().toggleOnTrue(shooter.shootersOffCommand());
+ operator.x().toggleOnTrue(shooter.conveyorOnCommand());
+ operator.y().toggleOnTrue(shooter.conveyorOffCommand());
+
+ pivot.setDefaultCommand(
+ PivotCommands.basicOperatorControl(
+ pivot, () -> operator.getRightX() - operator.getLeftX()));
+ }
+
+ /**
+ * Use this to pass the autonomous command to the main {@link Robot} class.
+ *
+ * @return the command to run in autonomous
+ */
+ public Command getAutonomousCommand() {
+ return autoChooser.get();
+ }
+}
diff --git a/src/main/java/frc/robot/commands/DriveCommands.java b/src/main/java/frc/robot/commands/DriveCommands.java
index e8d4faa..4ac9b75 100644
--- a/src/main/java/frc/robot/commands/DriveCommands.java
+++ b/src/main/java/frc/robot/commands/DriveCommands.java
@@ -1,70 +1,70 @@
-// Copyright 2021-2024 FRC 6328
-// http://github.com/Mechanical-Advantage
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// version 3 as published by the Free Software Foundation or
-// available in the root directory of this project.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-package frc.robot.commands;
-
-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.Transform2d;
-import edu.wpi.first.math.geometry.Translation2d;
-import edu.wpi.first.math.kinematics.ChassisSpeeds;
-import edu.wpi.first.wpilibj2.command.Command;
-import edu.wpi.first.wpilibj2.command.Commands;
-import frc.robot.subsystems.drive.Drive;
-import java.util.function.DoubleSupplier;
-
-public class DriveCommands {
- private static final double DEADBAND = 0.1;
-
- private DriveCommands() {}
-
- /**
- * Field relative drive command using two joysticks (controlling linear and angular velocities).
- */
- public static Command joystickDrive(
- Drive drive,
- DoubleSupplier xSupplier,
- DoubleSupplier ySupplier,
- DoubleSupplier omegaSupplier) {
- return Commands.run(
- () -> {
- // Apply deadband
- double linearMagnitude =
- MathUtil.applyDeadband(
- Math.hypot(xSupplier.getAsDouble(), ySupplier.getAsDouble()), DEADBAND);
- Rotation2d linearDirection =
- new Rotation2d(xSupplier.getAsDouble(), ySupplier.getAsDouble());
- double omega = MathUtil.applyDeadband(omegaSupplier.getAsDouble(), DEADBAND);
-
- // Square values
- linearMagnitude = linearMagnitude * linearMagnitude;
- omega = Math.copySign(omega * omega, omega);
-
- // Calcaulate new linear velocity
- Translation2d linearVelocity =
- new Pose2d(new Translation2d(), linearDirection)
- .transformBy(new Transform2d(linearMagnitude, 0.0, new Rotation2d()))
- .getTranslation();
-
- // Convert to field relative speeds & send command
- drive.runVelocity(
- ChassisSpeeds.fromFieldRelativeSpeeds(
- linearVelocity.getX() * drive.getMaxLinearSpeedMetersPerSec(),
- linearVelocity.getY() * drive.getMaxLinearSpeedMetersPerSec(),
- omega * drive.getMaxAngularSpeedRadPerSec(),
- drive.getRotation()));
- },
- drive);
- }
-}
+// Copyright 2021-2024 FRC 6328
+// http://github.com/Mechanical-Advantage
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 3 as published by the Free Software Foundation or
+// available in the root directory of this project.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+package frc.robot.commands;
+
+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.Transform2d;
+import edu.wpi.first.math.geometry.Translation2d;
+import edu.wpi.first.math.kinematics.ChassisSpeeds;
+import edu.wpi.first.wpilibj2.command.Command;
+import edu.wpi.first.wpilibj2.command.Commands;
+import frc.robot.subsystems.drive.Drive;
+import java.util.function.DoubleSupplier;
+
+public class DriveCommands {
+ private static final double DEADBAND = 0.1;
+
+ private DriveCommands() {}
+
+ /**
+ * Field relative drive command using two joysticks (controlling linear and angular velocities).
+ */
+ public static Command joystickDrive(
+ Drive drive,
+ DoubleSupplier xSupplier,
+ DoubleSupplier ySupplier,
+ DoubleSupplier omegaSupplier) {
+ return Commands.run(
+ () -> {
+ // Apply deadband
+ double linearMagnitude =
+ MathUtil.applyDeadband(
+ Math.hypot(xSupplier.getAsDouble(), ySupplier.getAsDouble()), DEADBAND);
+ Rotation2d linearDirection =
+ new Rotation2d(xSupplier.getAsDouble(), ySupplier.getAsDouble());
+ double omega = MathUtil.applyDeadband(omegaSupplier.getAsDouble(), DEADBAND);
+
+ // Square values
+ linearMagnitude = linearMagnitude * linearMagnitude;
+ omega = Math.copySign(omega * omega, omega);
+
+ // Calcaulate new linear velocity
+ Translation2d linearVelocity =
+ new Pose2d(new Translation2d(), linearDirection)
+ .transformBy(new Transform2d(linearMagnitude, 0.0, new Rotation2d()))
+ .getTranslation();
+
+ // Convert to field relative speeds & send command
+ drive.runVelocity(
+ ChassisSpeeds.fromFieldRelativeSpeeds(
+ linearVelocity.getX() * drive.getMaxLinearSpeedMetersPerSec(),
+ linearVelocity.getY() * drive.getMaxLinearSpeedMetersPerSec(),
+ omega * drive.getMaxAngularSpeedRadPerSec(),
+ drive.getRotation()));
+ },
+ drive);
+ }
+}
diff --git a/src/main/java/frc/robot/commands/FeedForwardCharacterization.java b/src/main/java/frc/robot/commands/FeedForwardCharacterization.java
index d7ac7a7..79b41c5 100644
--- a/src/main/java/frc/robot/commands/FeedForwardCharacterization.java
+++ b/src/main/java/frc/robot/commands/FeedForwardCharacterization.java
@@ -1,106 +1,106 @@
-// Copyright 2021-2024 FRC 6328
-// http://github.com/Mechanical-Advantage
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// version 3 as published by the Free Software Foundation or
-// available in the root directory of this project.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-package frc.robot.commands;
-
-import edu.wpi.first.wpilibj.Timer;
-import edu.wpi.first.wpilibj2.command.Command;
-import edu.wpi.first.wpilibj2.command.Subsystem;
-import frc.robot.util.PolynomialRegression;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.function.Consumer;
-import java.util.function.Supplier;
-
-public class FeedForwardCharacterization extends Command {
- private static final double START_DELAY_SECS = 2.0;
- private static final double RAMP_VOLTS_PER_SEC = 0.1;
-
- private FeedForwardCharacterizationData data;
- private final Consumer voltageConsumer;
- private final Supplier velocitySupplier;
-
- private final Timer timer = new Timer();
-
- /** Creates a new FeedForwardCharacterization command. */
- public FeedForwardCharacterization(
- Subsystem subsystem, Consumer voltageConsumer, Supplier velocitySupplier) {
- addRequirements(subsystem);
- this.voltageConsumer = voltageConsumer;
- this.velocitySupplier = velocitySupplier;
- }
-
- // Called when the command is initially scheduled.
- @Override
- public void initialize() {
- data = new FeedForwardCharacterizationData();
- timer.reset();
- timer.start();
- }
-
- // Called every time the scheduler runs while the command is scheduled.
- @Override
- public void execute() {
- if (timer.get() < START_DELAY_SECS) {
- voltageConsumer.accept(0.0);
- } else {
- double voltage = (timer.get() - START_DELAY_SECS) * RAMP_VOLTS_PER_SEC;
- voltageConsumer.accept(voltage);
- data.add(velocitySupplier.get(), voltage);
- }
- }
-
- // Called once the command ends or is interrupted.
- @Override
- public void end(boolean interrupted) {
- voltageConsumer.accept(0.0);
- timer.stop();
- data.print();
- }
-
- // Returns true when the command should end.
- @Override
- public boolean isFinished() {
- return false;
- }
-
- public static class FeedForwardCharacterizationData {
- private final List velocityData = new LinkedList<>();
- private final List voltageData = new LinkedList<>();
-
- public void add(double velocity, double voltage) {
- if (Math.abs(velocity) > 1E-4) {
- velocityData.add(Math.abs(velocity));
- voltageData.add(Math.abs(voltage));
- }
- }
-
- public void print() {
- if (velocityData.size() == 0 || voltageData.size() == 0) {
- return;
- }
-
- PolynomialRegression regression =
- new PolynomialRegression(
- velocityData.stream().mapToDouble(Double::doubleValue).toArray(),
- voltageData.stream().mapToDouble(Double::doubleValue).toArray(),
- 1);
-
- System.out.println("FF Characterization Results:");
- System.out.println("\tCount=" + Integer.toString(velocityData.size()) + "");
- System.out.println(String.format("\tR2=%.5f", regression.R2()));
- System.out.println(String.format("\tkS=%.5f", regression.beta(0)));
- System.out.println(String.format("\tkV=%.5f", regression.beta(1)));
- }
- }
-}
+// Copyright 2021-2024 FRC 6328
+// http://github.com/Mechanical-Advantage
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 3 as published by the Free Software Foundation or
+// available in the root directory of this project.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+package frc.robot.commands;
+
+import edu.wpi.first.wpilibj.Timer;
+import edu.wpi.first.wpilibj2.command.Command;
+import edu.wpi.first.wpilibj2.command.Subsystem;
+import frc.robot.util.PolynomialRegression;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+public class FeedForwardCharacterization extends Command {
+ private static final double START_DELAY_SECS = 2.0;
+ private static final double RAMP_VOLTS_PER_SEC = 0.1;
+
+ private FeedForwardCharacterizationData data;
+ private final Consumer voltageConsumer;
+ private final Supplier velocitySupplier;
+
+ private final Timer timer = new Timer();
+
+ /** Creates a new FeedForwardCharacterization command. */
+ public FeedForwardCharacterization(
+ Subsystem subsystem, Consumer voltageConsumer, Supplier velocitySupplier) {
+ addRequirements(subsystem);
+ this.voltageConsumer = voltageConsumer;
+ this.velocitySupplier = velocitySupplier;
+ }
+
+ // Called when the command is initially scheduled.
+ @Override
+ public void initialize() {
+ data = new FeedForwardCharacterizationData();
+ timer.reset();
+ timer.start();
+ }
+
+ // Called every time the scheduler runs while the command is scheduled.
+ @Override
+ public void execute() {
+ if (timer.get() < START_DELAY_SECS) {
+ voltageConsumer.accept(0.0);
+ } else {
+ double voltage = (timer.get() - START_DELAY_SECS) * RAMP_VOLTS_PER_SEC;
+ voltageConsumer.accept(voltage);
+ data.add(velocitySupplier.get(), voltage);
+ }
+ }
+
+ // Called once the command ends or is interrupted.
+ @Override
+ public void end(boolean interrupted) {
+ voltageConsumer.accept(0.0);
+ timer.stop();
+ data.print();
+ }
+
+ // Returns true when the command should end.
+ @Override
+ public boolean isFinished() {
+ return false;
+ }
+
+ public static class FeedForwardCharacterizationData {
+ private final List velocityData = new LinkedList<>();
+ private final List voltageData = new LinkedList<>();
+
+ public void add(double velocity, double voltage) {
+ if (Math.abs(velocity) > 1E-4) {
+ velocityData.add(Math.abs(velocity));
+ voltageData.add(Math.abs(voltage));
+ }
+ }
+
+ public void print() {
+ if (velocityData.size() == 0 || voltageData.size() == 0) {
+ return;
+ }
+
+ PolynomialRegression regression =
+ new PolynomialRegression(
+ velocityData.stream().mapToDouble(Double::doubleValue).toArray(),
+ voltageData.stream().mapToDouble(Double::doubleValue).toArray(),
+ 1);
+
+ System.out.println("FF Characterization Results:");
+ System.out.println("\tCount=" + Integer.toString(velocityData.size()) + "");
+ System.out.println(String.format("\tR2=%.5f", regression.R2()));
+ System.out.println(String.format("\tkS=%.5f", regression.beta(0)));
+ System.out.println(String.format("\tkV=%.5f", regression.beta(1)));
+ }
+ }
+}
diff --git a/src/main/java/frc/robot/subsystems/drive/Drive.java b/src/main/java/frc/robot/subsystems/drive/Drive.java
index 3797f6b..265f05d 100644
--- a/src/main/java/frc/robot/subsystems/drive/Drive.java
+++ b/src/main/java/frc/robot/subsystems/drive/Drive.java
@@ -1,247 +1,247 @@
-// Copyright 2021-2024 FRC 6328
-// http://github.com/Mechanical-Advantage
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// version 3 as published by the Free Software Foundation or
-// available in the root directory of this project.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-package frc.robot.subsystems.drive;
-
-import com.pathplanner.lib.auto.AutoBuilder;
-import com.pathplanner.lib.pathfinding.Pathfinding;
-import com.pathplanner.lib.util.HolonomicPathFollowerConfig;
-import com.pathplanner.lib.util.PathPlannerLogging;
-import com.pathplanner.lib.util.ReplanningConfig;
-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.util.Units;
-import edu.wpi.first.wpilibj.DriverStation;
-import edu.wpi.first.wpilibj.DriverStation.Alliance;
-import edu.wpi.first.wpilibj2.command.SubsystemBase;
-import frc.robot.util.LocalADStarAK;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-import org.littletonrobotics.junction.AutoLogOutput;
-import org.littletonrobotics.junction.Logger;
-
-public class Drive extends SubsystemBase {
- private static final double MAX_LINEAR_SPEED = Units.feetToMeters(14.5);
- private static final double TRACK_WIDTH_X = Units.inchesToMeters(22.75);
- private static final double TRACK_WIDTH_Y = Units.inchesToMeters(18.75);
- private static final double DRIVE_BASE_RADIUS =
- Math.hypot(TRACK_WIDTH_X / 2.0, TRACK_WIDTH_Y / 2.0);
- private static final double MAX_ANGULAR_SPEED = MAX_LINEAR_SPEED / DRIVE_BASE_RADIUS;
-
- public static final Lock odometryLock = new ReentrantLock();
- private final GyroIO gyroIO;
- private final GyroIOInputsAutoLogged gyroInputs = new GyroIOInputsAutoLogged();
- private final Module[] modules = new Module[4]; // FL, FR, BL, BR
-
- private SwerveDriveKinematics kinematics = new SwerveDriveKinematics(getModuleTranslations());
- private Pose2d pose = new Pose2d();
- private Rotation2d lastGyroRotation = new Rotation2d();
-
- public Drive(
- GyroIO gyroIO,
- ModuleIO flModuleIO,
- ModuleIO frModuleIO,
- ModuleIO blModuleIO,
- ModuleIO brModuleIO) {
- this.gyroIO = gyroIO;
- modules[0] = new Module(flModuleIO, 0);
- modules[1] = new Module(frModuleIO, 1);
- modules[2] = new Module(blModuleIO, 2);
- modules[3] = new Module(brModuleIO, 3);
-
- // Configure AutoBuilder for PathPlanner
- AutoBuilder.configureHolonomic(
- this::getPose,
- this::setPose,
- () -> kinematics.toChassisSpeeds(getModuleStates()),
- this::runVelocity,
- new HolonomicPathFollowerConfig(
- MAX_LINEAR_SPEED, DRIVE_BASE_RADIUS, new ReplanningConfig()),
- () ->
- DriverStation.getAlliance().isPresent()
- && DriverStation.getAlliance().get() == Alliance.Red,
- this);
- Pathfinding.setPathfinder(new LocalADStarAK());
- PathPlannerLogging.setLogActivePathCallback(
- (activePath) -> {
- Logger.recordOutput(
- "Odometry/Trajectory", activePath.toArray(new Pose2d[activePath.size()]));
- });
- PathPlannerLogging.setLogTargetPoseCallback(
- (targetPose) -> {
- Logger.recordOutput("Odometry/TrajectorySetpoint", targetPose);
- });
- }
-
- public void periodic() {
- odometryLock.lock(); // Prevents odometry updates while reading data
- gyroIO.updateInputs(gyroInputs);
- for (var module : modules) {
- module.updateInputs();
- }
- odometryLock.unlock();
- Logger.processInputs("Drive/Gyro", gyroInputs);
- for (var module : modules) {
- module.periodic();
- }
-
- // Stop moving when disabled
- if (DriverStation.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[] {});
- }
-
- // Update odometry
- int deltaCount =
- gyroInputs.connected ? gyroInputs.odometryYawPositions.length : Integer.MAX_VALUE;
- for (int i = 0; i < 4; i++) {
- deltaCount = Math.min(deltaCount, modules[i].getPositionDeltas().length);
- }
- for (int deltaIndex = 0; deltaIndex < deltaCount; deltaIndex++) {
- // Read wheel deltas from each module
- SwerveModulePosition[] wheelDeltas = new SwerveModulePosition[4];
- for (int moduleIndex = 0; moduleIndex < 4; moduleIndex++) {
- wheelDeltas[moduleIndex] = modules[moduleIndex].getPositionDeltas()[deltaIndex];
- }
-
- // The twist represents the motion of the robot since the last
- // sample in x, y, and theta based only on the modules, without
- // the gyro. The gyro is always disconnected in simulation.
- var twist = kinematics.toTwist2d(wheelDeltas);
- if (gyroInputs.connected) {
- // If the gyro is connected, replace the theta component of the twist
- // with the change in angle since the last sample.
- Rotation2d gyroRotation = gyroInputs.odometryYawPositions[deltaIndex];
- twist = new Twist2d(twist.dx, twist.dy, gyroRotation.minus(lastGyroRotation).getRadians());
- lastGyroRotation = gyroRotation;
- }
- // Apply the twist (change since last sample) to the current pose
- pose = pose.exp(twist);
- }
- }
-
- /**
- * Runs the drive at the desired velocity.
- *
- * @param speeds Speeds in meters/sec
- */
- public void runVelocity(ChassisSpeeds speeds) {
- // Calculate module setpoints
- ChassisSpeeds discreteSpeeds = ChassisSpeeds.discretize(speeds, 0.02);
- SwerveModuleState[] setpointStates = kinematics.toSwerveModuleStates(discreteSpeeds);
- SwerveDriveKinematics.desaturateWheelSpeeds(setpointStates, MAX_LINEAR_SPEED);
-
- // Send setpoints to modules
- SwerveModuleState[] optimizedSetpointStates = new SwerveModuleState[4];
- for (int i = 0; i < 4; i++) {
- // The module returns the optimized state, useful for logging
- optimizedSetpointStates[i] = modules[i].runSetpoint(setpointStates[i]);
- }
-
- // Log setpoint states
- Logger.recordOutput("SwerveStates/Setpoints", setpointStates);
- Logger.recordOutput("SwerveStates/SetpointsOptimized", optimizedSetpointStates);
- }
-
- /** Stops the drive. */
- public void stop() {
- runVelocity(new ChassisSpeeds());
- }
-
- /**
- * Stops the drive and turns the modules to an X arrangement to resist movement. The modules will
- * return to their normal orientations the next time a nonzero velocity is requested.
- */
- public void stopWithX() {
- Rotation2d[] headings = new Rotation2d[4];
- for (int i = 0; i < 4; i++) {
- headings[i] = getModuleTranslations()[i].getAngle();
- }
- kinematics.resetHeadings(headings);
- stop();
- }
-
- /** Runs forwards at the commanded voltage. */
- public void runCharacterizationVolts(double volts) {
- for (int i = 0; i < 4; i++) {
- modules[i].runCharacterization(volts);
- }
- }
-
- /** Returns the average drive velocity in radians/sec. */
- public double getCharacterizationVelocity() {
- double driveVelocityAverage = 0.0;
- for (var module : modules) {
- driveVelocityAverage += module.getCharacterizationVelocity();
- }
- return driveVelocityAverage / 4.0;
- }
-
- /** 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];
- for (int i = 0; i < 4; i++) {
- states[i] = modules[i].getState();
- }
- return states;
- }
-
- /** Returns the current odometry pose. */
- @AutoLogOutput(key = "Odometry/Robot")
- public Pose2d getPose() {
- return pose;
- }
-
- /** Returns the current odometry rotation. */
- public Rotation2d getRotation() {
- return pose.getRotation();
- }
-
- /** Resets the current odometry pose. */
- public void setPose(Pose2d pose) {
- this.pose = pose;
- }
-
- /** Returns the maximum linear speed in meters per sec. */
- public double getMaxLinearSpeedMetersPerSec() {
- return MAX_LINEAR_SPEED;
- }
-
- /** Returns the maximum angular speed in radians per sec. */
- public double getMaxAngularSpeedRadPerSec() {
- return MAX_ANGULAR_SPEED;
- }
-
- /** Returns an array of module translations. */
- public static Translation2d[] getModuleTranslations() {
- return new Translation2d[] {
- new Translation2d(TRACK_WIDTH_X / 2.0, TRACK_WIDTH_Y / 2.0),
- new Translation2d(TRACK_WIDTH_X / 2.0, -TRACK_WIDTH_Y / 2.0),
- new Translation2d(-TRACK_WIDTH_X / 2.0, TRACK_WIDTH_Y / 2.0),
- new Translation2d(-TRACK_WIDTH_X / 2.0, -TRACK_WIDTH_Y / 2.0)
- };
- }
-}
+// Copyright 2021-2024 FRC 6328
+// http://github.com/Mechanical-Advantage
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 3 as published by the Free Software Foundation or
+// available in the root directory of this project.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+package frc.robot.subsystems.drive;
+
+import com.pathplanner.lib.auto.AutoBuilder;
+import com.pathplanner.lib.pathfinding.Pathfinding;
+import com.pathplanner.lib.util.HolonomicPathFollowerConfig;
+import com.pathplanner.lib.util.PathPlannerLogging;
+import com.pathplanner.lib.util.ReplanningConfig;
+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.util.Units;
+import edu.wpi.first.wpilibj.DriverStation;
+import edu.wpi.first.wpilibj.DriverStation.Alliance;
+import edu.wpi.first.wpilibj2.command.SubsystemBase;
+import frc.robot.util.LocalADStarAK;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import org.littletonrobotics.junction.AutoLogOutput;
+import org.littletonrobotics.junction.Logger;
+
+public class Drive extends SubsystemBase {
+ private static final double MAX_LINEAR_SPEED = Units.feetToMeters(14.5);
+ private static final double TRACK_WIDTH_X = Units.inchesToMeters(22.75);
+ private static final double TRACK_WIDTH_Y = Units.inchesToMeters(18.75);
+ private static final double DRIVE_BASE_RADIUS =
+ Math.hypot(TRACK_WIDTH_X / 2.0, TRACK_WIDTH_Y / 2.0);
+ private static final double MAX_ANGULAR_SPEED = MAX_LINEAR_SPEED / DRIVE_BASE_RADIUS;
+
+ public static final Lock odometryLock = new ReentrantLock();
+ private final GyroIO gyroIO;
+ private final GyroIOInputsAutoLogged gyroInputs = new GyroIOInputsAutoLogged();
+ private final Module[] modules = new Module[4]; // FL, FR, BL, BR
+
+ private SwerveDriveKinematics kinematics = new SwerveDriveKinematics(getModuleTranslations());
+ private Pose2d pose = new Pose2d();
+ private Rotation2d lastGyroRotation = new Rotation2d();
+
+ public Drive(
+ GyroIO gyroIO,
+ ModuleIO flModuleIO,
+ ModuleIO frModuleIO,
+ ModuleIO blModuleIO,
+ ModuleIO brModuleIO) {
+ this.gyroIO = gyroIO;
+ modules[0] = new Module(flModuleIO, 0);
+ modules[1] = new Module(frModuleIO, 1);
+ modules[2] = new Module(blModuleIO, 2);
+ modules[3] = new Module(brModuleIO, 3);
+
+ // Configure AutoBuilder for PathPlanner
+ AutoBuilder.configureHolonomic(
+ this::getPose,
+ this::setPose,
+ () -> kinematics.toChassisSpeeds(getModuleStates()),
+ this::runVelocity,
+ new HolonomicPathFollowerConfig(
+ MAX_LINEAR_SPEED, DRIVE_BASE_RADIUS, new ReplanningConfig()),
+ () ->
+ DriverStation.getAlliance().isPresent()
+ && DriverStation.getAlliance().get() == Alliance.Red,
+ this);
+ Pathfinding.setPathfinder(new LocalADStarAK());
+ PathPlannerLogging.setLogActivePathCallback(
+ (activePath) -> {
+ Logger.recordOutput(
+ "Odometry/Trajectory", activePath.toArray(new Pose2d[activePath.size()]));
+ });
+ PathPlannerLogging.setLogTargetPoseCallback(
+ (targetPose) -> {
+ Logger.recordOutput("Odometry/TrajectorySetpoint", targetPose);
+ });
+ }
+
+ public void periodic() {
+ odometryLock.lock(); // Prevents odometry updates while reading data
+ gyroIO.updateInputs(gyroInputs);
+ for (var module : modules) {
+ module.updateInputs();
+ }
+ odometryLock.unlock();
+ Logger.processInputs("Drive/Gyro", gyroInputs);
+ for (var module : modules) {
+ module.periodic();
+ }
+
+ // Stop moving when disabled
+ if (DriverStation.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[] {});
+ }
+
+ // Update odometry
+ int deltaCount =
+ gyroInputs.connected ? gyroInputs.odometryYawPositions.length : Integer.MAX_VALUE;
+ for (int i = 0; i < 4; i++) {
+ deltaCount = Math.min(deltaCount, modules[i].getPositionDeltas().length);
+ }
+ for (int deltaIndex = 0; deltaIndex < deltaCount; deltaIndex++) {
+ // Read wheel deltas from each module
+ SwerveModulePosition[] wheelDeltas = new SwerveModulePosition[4];
+ for (int moduleIndex = 0; moduleIndex < 4; moduleIndex++) {
+ wheelDeltas[moduleIndex] = modules[moduleIndex].getPositionDeltas()[deltaIndex];
+ }
+
+ // The twist represents the motion of the robot since the last
+ // sample in x, y, and theta based only on the modules, without
+ // the gyro. The gyro is always disconnected in simulation.
+ var twist = kinematics.toTwist2d(wheelDeltas);
+ if (gyroInputs.connected) {
+ // If the gyro is connected, replace the theta component of the twist
+ // with the change in angle since the last sample.
+ Rotation2d gyroRotation = gyroInputs.odometryYawPositions[deltaIndex];
+ twist = new Twist2d(twist.dx, twist.dy, gyroRotation.minus(lastGyroRotation).getRadians());
+ lastGyroRotation = gyroRotation;
+ }
+ // Apply the twist (change since last sample) to the current pose
+ pose = pose.exp(twist);
+ }
+ }
+
+ /**
+ * Runs the drive at the desired velocity.
+ *
+ * @param speeds Speeds in meters/sec
+ */
+ public void runVelocity(ChassisSpeeds speeds) {
+ // Calculate module setpoints
+ ChassisSpeeds discreteSpeeds = ChassisSpeeds.discretize(speeds, 0.02);
+ SwerveModuleState[] setpointStates = kinematics.toSwerveModuleStates(discreteSpeeds);
+ SwerveDriveKinematics.desaturateWheelSpeeds(setpointStates, MAX_LINEAR_SPEED);
+
+ // Send setpoints to modules
+ SwerveModuleState[] optimizedSetpointStates = new SwerveModuleState[4];
+ for (int i = 0; i < 4; i++) {
+ // The module returns the optimized state, useful for logging
+ optimizedSetpointStates[i] = modules[i].runSetpoint(setpointStates[i]);
+ }
+
+ // Log setpoint states
+ Logger.recordOutput("SwerveStates/Setpoints", setpointStates);
+ Logger.recordOutput("SwerveStates/SetpointsOptimized", optimizedSetpointStates);
+ }
+
+ /** Stops the drive. */
+ public void stop() {
+ runVelocity(new ChassisSpeeds());
+ }
+
+ /**
+ * Stops the drive and turns the modules to an X arrangement to resist movement. The modules will
+ * return to their normal orientations the next time a nonzero velocity is requested.
+ */
+ public void stopWithX() {
+ Rotation2d[] headings = new Rotation2d[4];
+ for (int i = 0; i < 4; i++) {
+ headings[i] = getModuleTranslations()[i].getAngle();
+ }
+ kinematics.resetHeadings(headings);
+ stop();
+ }
+
+ /** Runs forwards at the commanded voltage. */
+ public void runCharacterizationVolts(double volts) {
+ for (int i = 0; i < 4; i++) {
+ modules[i].runCharacterization(volts);
+ }
+ }
+
+ /** Returns the average drive velocity in radians/sec. */
+ public double getCharacterizationVelocity() {
+ double driveVelocityAverage = 0.0;
+ for (var module : modules) {
+ driveVelocityAverage += module.getCharacterizationVelocity();
+ }
+ return driveVelocityAverage / 4.0;
+ }
+
+ /** 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];
+ for (int i = 0; i < 4; i++) {
+ states[i] = modules[i].getState();
+ }
+ return states;
+ }
+
+ /** Returns the current odometry pose. */
+ @AutoLogOutput(key = "Odometry/Robot")
+ public Pose2d getPose() {
+ return pose;
+ }
+
+ /** Returns the current odometry rotation. */
+ public Rotation2d getRotation() {
+ return pose.getRotation();
+ }
+
+ /** Resets the current odometry pose. */
+ public void setPose(Pose2d pose) {
+ this.pose = pose;
+ }
+
+ /** Returns the maximum linear speed in meters per sec. */
+ public double getMaxLinearSpeedMetersPerSec() {
+ return MAX_LINEAR_SPEED;
+ }
+
+ /** Returns the maximum angular speed in radians per sec. */
+ public double getMaxAngularSpeedRadPerSec() {
+ return MAX_ANGULAR_SPEED;
+ }
+
+ /** Returns an array of module translations. */
+ public static Translation2d[] getModuleTranslations() {
+ return new Translation2d[] {
+ new Translation2d(TRACK_WIDTH_X / 2.0, TRACK_WIDTH_Y / 2.0),
+ new Translation2d(TRACK_WIDTH_X / 2.0, -TRACK_WIDTH_Y / 2.0),
+ new Translation2d(-TRACK_WIDTH_X / 2.0, TRACK_WIDTH_Y / 2.0),
+ new Translation2d(-TRACK_WIDTH_X / 2.0, -TRACK_WIDTH_Y / 2.0)
+ };
+ }
+}
diff --git a/src/main/java/frc/robot/subsystems/drive/GyroIO.java b/src/main/java/frc/robot/subsystems/drive/GyroIO.java
index 38ccec1..65cde8e 100644
--- a/src/main/java/frc/robot/subsystems/drive/GyroIO.java
+++ b/src/main/java/frc/robot/subsystems/drive/GyroIO.java
@@ -1,29 +1,29 @@
-// Copyright 2021-2024 FRC 6328
-// http://github.com/Mechanical-Advantage
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// version 3 as published by the Free Software Foundation or
-// available in the root directory of this project.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-package frc.robot.subsystems.drive;
-
-import edu.wpi.first.math.geometry.Rotation2d;
-import org.littletonrobotics.junction.AutoLog;
-
-public interface GyroIO {
- @AutoLog
- public static class GyroIOInputs {
- public boolean connected = false;
- public Rotation2d yawPosition = new Rotation2d();
- public Rotation2d[] odometryYawPositions = new Rotation2d[] {};
- public double yawVelocityRadPerSec = 0.0;
- }
-
- public default void updateInputs(GyroIOInputs inputs) {}
-}
+// Copyright 2021-2024 FRC 6328
+// http://github.com/Mechanical-Advantage
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 3 as published by the Free Software Foundation or
+// available in the root directory of this project.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+package frc.robot.subsystems.drive;
+
+import edu.wpi.first.math.geometry.Rotation2d;
+import org.littletonrobotics.junction.AutoLog;
+
+public interface GyroIO {
+ @AutoLog
+ public static class GyroIOInputs {
+ public boolean connected = false;
+ public Rotation2d yawPosition = new Rotation2d();
+ public Rotation2d[] odometryYawPositions = new Rotation2d[] {};
+ public double yawVelocityRadPerSec = 0.0;
+ }
+
+ public default void updateInputs(GyroIOInputs inputs) {}
+}
diff --git a/src/main/java/frc/robot/subsystems/drive/GyroIOPigeon2.java b/src/main/java/frc/robot/subsystems/drive/GyroIOPigeon2.java
index 49a6a56..55265cf 100644
--- a/src/main/java/frc/robot/subsystems/drive/GyroIOPigeon2.java
+++ b/src/main/java/frc/robot/subsystems/drive/GyroIOPigeon2.java
@@ -1,53 +1,53 @@
-// Copyright 2021-2024 FRC 6328
-// http://github.com/Mechanical-Advantage
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// version 3 as published by the Free Software Foundation or
-// available in the root directory of this project.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-package frc.robot.subsystems.drive;
-
-import com.ctre.phoenix6.BaseStatusSignal;
-import com.ctre.phoenix6.StatusCode;
-import com.ctre.phoenix6.StatusSignal;
-import com.ctre.phoenix6.configs.Pigeon2Configuration;
-import com.ctre.phoenix6.hardware.Pigeon2;
-import edu.wpi.first.math.geometry.Rotation2d;
-import edu.wpi.first.math.util.Units;
-import java.util.Queue;
-
-/** IO implementation for Pigeon2 */
-public class GyroIOPigeon2 implements GyroIO {
- private final Pigeon2 pigeon = new Pigeon2(20);
- private final StatusSignal yaw = pigeon.getYaw();
- private final Queue yawPositionQueue;
- private final StatusSignal yawVelocity = pigeon.getAngularVelocityZWorld();
-
- public GyroIOPigeon2(boolean phoenixDrive) {
- pigeon.getConfigurator().apply(new Pigeon2Configuration());
- pigeon.getConfigurator().setYaw(0.0);
- yaw.setUpdateFrequency(Module.ODOMETRY_FREQUENCY);
- yawVelocity.setUpdateFrequency(100.0);
- pigeon.optimizeBusUtilization();
- yawPositionQueue = PhoenixOdometryThread.getInstance().registerSignal(pigeon, pigeon.getYaw());
- }
-
- @Override
- public void updateInputs(GyroIOInputs inputs) {
- inputs.connected = BaseStatusSignal.refreshAll(yaw, yawVelocity).equals(StatusCode.OK);
- inputs.yawPosition = Rotation2d.fromDegrees(yaw.getValueAsDouble());
- inputs.yawVelocityRadPerSec = Units.degreesToRadians(yawVelocity.getValueAsDouble());
-
- inputs.odometryYawPositions =
- yawPositionQueue.stream()
- .map((Double value) -> Rotation2d.fromDegrees(value))
- .toArray(Rotation2d[]::new);
- yawPositionQueue.clear();
- }
-}
+// Copyright 2021-2024 FRC 6328
+// http://github.com/Mechanical-Advantage
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 3 as published by the Free Software Foundation or
+// available in the root directory of this project.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+package frc.robot.subsystems.drive;
+
+import com.ctre.phoenix6.BaseStatusSignal;
+import com.ctre.phoenix6.StatusCode;
+import com.ctre.phoenix6.StatusSignal;
+import com.ctre.phoenix6.configs.Pigeon2Configuration;
+import com.ctre.phoenix6.hardware.Pigeon2;
+import edu.wpi.first.math.geometry.Rotation2d;
+import edu.wpi.first.math.util.Units;
+import java.util.Queue;
+
+/** IO implementation for Pigeon2 */
+public class GyroIOPigeon2 implements GyroIO {
+ private final Pigeon2 pigeon = new Pigeon2(20);
+ private final StatusSignal yaw = pigeon.getYaw();
+ private final Queue yawPositionQueue;
+ private final StatusSignal yawVelocity = pigeon.getAngularVelocityZWorld();
+
+ public GyroIOPigeon2(boolean phoenixDrive) {
+ pigeon.getConfigurator().apply(new Pigeon2Configuration());
+ pigeon.getConfigurator().setYaw(0.0);
+ yaw.setUpdateFrequency(Module.ODOMETRY_FREQUENCY);
+ yawVelocity.setUpdateFrequency(100.0);
+ pigeon.optimizeBusUtilization();
+ yawPositionQueue = PhoenixOdometryThread.getInstance().registerSignal(pigeon, pigeon.getYaw());
+ }
+
+ @Override
+ public void updateInputs(GyroIOInputs inputs) {
+ inputs.connected = BaseStatusSignal.refreshAll(yaw, yawVelocity).equals(StatusCode.OK);
+ inputs.yawPosition = Rotation2d.fromDegrees(yaw.getValueAsDouble());
+ inputs.yawVelocityRadPerSec = Units.degreesToRadians(yawVelocity.getValueAsDouble());
+
+ inputs.odometryYawPositions =
+ yawPositionQueue.stream()
+ .map((Double value) -> Rotation2d.fromDegrees(value))
+ .toArray(Rotation2d[]::new);
+ yawPositionQueue.clear();
+ }
+}
diff --git a/src/main/java/frc/robot/subsystems/drive/Module.java b/src/main/java/frc/robot/subsystems/drive/Module.java
index 59dfb2a..f8311ea 100644
--- a/src/main/java/frc/robot/subsystems/drive/Module.java
+++ b/src/main/java/frc/robot/subsystems/drive/Module.java
@@ -1,202 +1,202 @@
-// Copyright 2021-2024 FRC 6328
-// http://github.com/Mechanical-Advantage
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// version 3 as published by the Free Software Foundation or
-// available in the root directory of this project.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-package frc.robot.subsystems.drive;
-
-import edu.wpi.first.math.controller.PIDController;
-import edu.wpi.first.math.controller.SimpleMotorFeedforward;
-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 frc.robot.Constants;
-import org.littletonrobotics.junction.Logger;
-
-public class Module {
- private static final double WHEEL_RADIUS = Units.inchesToMeters(2.0);
- public static final double ODOMETRY_FREQUENCY = 250.0;
-
- private final ModuleIO io;
- private final ModuleIOInputsAutoLogged inputs = new ModuleIOInputsAutoLogged();
- private final int index;
-
- private final SimpleMotorFeedforward driveFeedforward;
- private final PIDController driveFeedback;
- private final PIDController turnFeedback;
- private Rotation2d angleSetpoint = null; // Setpoint for closed loop control, null for open loop
- private Double speedSetpoint = null; // Setpoint for closed loop control, null for open loop
- private Rotation2d turnRelativeOffset = null; // Relative + Offset = Absolute
- private double lastPositionMeters = 0.0; // Used for delta calculation
- private SwerveModulePosition[] positionDeltas = new SwerveModulePosition[] {};
-
- public Module(ModuleIO io, int index) {
- this.io = io;
- this.index = index;
-
- // Switch constants based on mode (the physics simulator is treated as a
- // separate robot with different tuning)
- switch (Constants.currentMode) {
- case REAL:
- case REPLAY:
- driveFeedforward = new SimpleMotorFeedforward(0.1, 0.13);
- driveFeedback = new PIDController(0.05, 0.0, 0.0);
- turnFeedback = new PIDController(7.0, 0.0, 0.0);
- break;
- case SIM:
- driveFeedforward = new SimpleMotorFeedforward(0.0, 0.13);
- driveFeedback = new PIDController(0.1, 0.0, 0.0);
- turnFeedback = new PIDController(10.0, 0.0, 0.0);
- break;
- default:
- driveFeedforward = new SimpleMotorFeedforward(0.0, 0.0);
- driveFeedback = new PIDController(0.0, 0.0, 0.0);
- turnFeedback = new PIDController(0.0, 0.0, 0.0);
- break;
- }
-
- turnFeedback.enableContinuousInput(-Math.PI, Math.PI);
- setBrakeMode(true);
- }
-
- /**
- * Update inputs without running the rest of the periodic logic. This is useful since these
- * updates need to be properly thread-locked.
- */
- public void updateInputs() {
- io.updateInputs(inputs);
- }
-
- public void periodic() {
- Logger.processInputs("Drive/Module" + Integer.toString(index), inputs);
-
- // On first cycle, reset relative turn encoder
- // Wait until absolute angle is nonzero in case it wasn't initialized yet
- if (turnRelativeOffset == null && inputs.turnAbsolutePosition.getRadians() != 0.0) {
- turnRelativeOffset = inputs.turnAbsolutePosition.minus(inputs.turnPosition);
- }
-
- // Run closed loop turn control
- if (angleSetpoint != null) {
- io.setTurnVoltage(
- turnFeedback.calculate(getAngle().getRadians(), angleSetpoint.getRadians()));
-
- // Run closed loop drive control
- // Only allowed if closed loop turn control is running
- if (speedSetpoint != null) {
- // Scale velocity based on turn error
- //
- // When the error is 90°, the velocity setpoint should be 0. As the wheel turns
- // towards the setpoint, its velocity should increase. This is achieved by
- // taking the component of the velocity in the direction of the setpoint.
- double adjustSpeedSetpoint = speedSetpoint * Math.cos(turnFeedback.getPositionError());
-
- // Run drive controller
- double velocityRadPerSec = adjustSpeedSetpoint / WHEEL_RADIUS;
- io.setDriveVoltage(
- driveFeedforward.calculate(velocityRadPerSec)
- + driveFeedback.calculate(inputs.driveVelocityRadPerSec, velocityRadPerSec));
- }
- }
-
- // Calculate position deltas for odometry
- int deltaCount =
- Math.min(inputs.odometryDrivePositionsRad.length, inputs.odometryTurnPositions.length);
- positionDeltas = new SwerveModulePosition[deltaCount];
- for (int i = 0; i < deltaCount; i++) {
- double positionMeters = inputs.odometryDrivePositionsRad[i] * WHEEL_RADIUS;
- Rotation2d angle =
- inputs.odometryTurnPositions[i].plus(
- turnRelativeOffset != null ? turnRelativeOffset : new Rotation2d());
- positionDeltas[i] = new SwerveModulePosition(positionMeters - lastPositionMeters, angle);
- lastPositionMeters = positionMeters;
- }
- }
-
- /** Runs the module with the specified setpoint state. Returns the optimized state. */
- public SwerveModuleState runSetpoint(SwerveModuleState state) {
- // Optimize state based on current angle
- // Controllers run in "periodic" when the setpoint is not null
- var optimizedState = SwerveModuleState.optimize(state, getAngle());
-
- // Update setpoints, controllers run in "periodic"
- angleSetpoint = optimizedState.angle;
- speedSetpoint = optimizedState.speedMetersPerSecond;
-
- return optimizedState;
- }
-
- /** Runs the module with the specified voltage while controlling to zero degrees. */
- public void runCharacterization(double volts) {
- // Closed loop turn control
- angleSetpoint = new Rotation2d();
-
- // Open loop drive control
- io.setDriveVoltage(volts);
- speedSetpoint = null;
- }
-
- /** Disables all outputs to motors. */
- public void stop() {
- io.setTurnVoltage(0.0);
- io.setDriveVoltage(0.0);
-
- // Disable closed loop control for turn and drive
- angleSetpoint = null;
- speedSetpoint = null;
- }
-
- /** Sets whether brake mode is enabled. */
- public void setBrakeMode(boolean enabled) {
- io.setDriveBrakeMode(enabled);
- io.setTurnBrakeMode(enabled);
- }
-
- /** Returns the current turn angle of the module. */
- public Rotation2d getAngle() {
- if (turnRelativeOffset == null) {
- return new Rotation2d();
- } else {
- return inputs.turnPosition.plus(turnRelativeOffset);
- }
- }
-
- /** Returns the current drive position of the module in meters. */
- public double getPositionMeters() {
- return inputs.drivePositionRad * WHEEL_RADIUS;
- }
-
- /** Returns the current drive velocity of the module in meters per second. */
- public double getVelocityMetersPerSec() {
- return inputs.driveVelocityRadPerSec * WHEEL_RADIUS;
- }
-
- /** Returns the module position (turn angle and drive position). */
- public SwerveModulePosition getPosition() {
- return new SwerveModulePosition(getPositionMeters(), getAngle());
- }
-
- /** Returns the module state (turn angle and drive velocity). */
- public SwerveModuleState getState() {
- return new SwerveModuleState(getVelocityMetersPerSec(), getAngle());
- }
-
- /** Returns the module position deltas received this cycle. */
- public SwerveModulePosition[] getPositionDeltas() {
- return positionDeltas;
- }
-
- /** Returns the drive velocity in radians/sec. */
- public double getCharacterizationVelocity() {
- return inputs.driveVelocityRadPerSec;
- }
-}
+// Copyright 2021-2024 FRC 6328
+// http://github.com/Mechanical-Advantage
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 3 as published by the Free Software Foundation or
+// available in the root directory of this project.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+package frc.robot.subsystems.drive;
+
+import edu.wpi.first.math.controller.PIDController;
+import edu.wpi.first.math.controller.SimpleMotorFeedforward;
+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 frc.robot.Constants;
+import org.littletonrobotics.junction.Logger;
+
+public class Module {
+ private static final double WHEEL_RADIUS = Units.inchesToMeters(2.0);
+ public static final double ODOMETRY_FREQUENCY = 250.0;
+
+ private final ModuleIO io;
+ private final ModuleIOInputsAutoLogged inputs = new ModuleIOInputsAutoLogged();
+ private final int index;
+
+ private final SimpleMotorFeedforward driveFeedforward;
+ private final PIDController driveFeedback;
+ private final PIDController turnFeedback;
+ private Rotation2d angleSetpoint = null; // Setpoint for closed loop control, null for open loop
+ private Double speedSetpoint = null; // Setpoint for closed loop control, null for open loop
+ private Rotation2d turnRelativeOffset = null; // Relative + Offset = Absolute
+ private double lastPositionMeters = 0.0; // Used for delta calculation
+ private SwerveModulePosition[] positionDeltas = new SwerveModulePosition[] {};
+
+ public Module(ModuleIO io, int index) {
+ this.io = io;
+ this.index = index;
+
+ // Switch constants based on mode (the physics simulator is treated as a
+ // separate robot with different tuning)
+ switch (Constants.currentMode) {
+ case REAL:
+ case REPLAY:
+ driveFeedforward = new SimpleMotorFeedforward(0.1, 0.13);
+ driveFeedback = new PIDController(0.05, 0.0, 0.0);
+ turnFeedback = new PIDController(7.0, 0.0, 0.0);
+ break;
+ case SIM:
+ driveFeedforward = new SimpleMotorFeedforward(0.0, 0.13);
+ driveFeedback = new PIDController(0.1, 0.0, 0.0);
+ turnFeedback = new PIDController(10.0, 0.0, 0.0);
+ break;
+ default:
+ driveFeedforward = new SimpleMotorFeedforward(0.0, 0.0);
+ driveFeedback = new PIDController(0.0, 0.0, 0.0);
+ turnFeedback = new PIDController(0.0, 0.0, 0.0);
+ break;
+ }
+
+ turnFeedback.enableContinuousInput(-Math.PI, Math.PI);
+ setBrakeMode(true);
+ }
+
+ /**
+ * Update inputs without running the rest of the periodic logic. This is useful since these
+ * updates need to be properly thread-locked.
+ */
+ public void updateInputs() {
+ io.updateInputs(inputs);
+ }
+
+ public void periodic() {
+ Logger.processInputs("Drive/Module" + Integer.toString(index), inputs);
+
+ // On first cycle, reset relative turn encoder
+ // Wait until absolute angle is nonzero in case it wasn't initialized yet
+ if (turnRelativeOffset == null && inputs.turnAbsolutePosition.getRadians() != 0.0) {
+ turnRelativeOffset = inputs.turnAbsolutePosition.minus(inputs.turnPosition);
+ }
+
+ // Run closed loop turn control
+ if (angleSetpoint != null) {
+ io.setTurnVoltage(
+ turnFeedback.calculate(getAngle().getRadians(), angleSetpoint.getRadians()));
+
+ // Run closed loop drive control
+ // Only allowed if closed loop turn control is running
+ if (speedSetpoint != null) {
+ // Scale velocity based on turn error
+ //
+ // When the error is 90°, the velocity setpoint should be 0. As the wheel turns
+ // towards the setpoint, its velocity should increase. This is achieved by
+ // taking the component of the velocity in the direction of the setpoint.
+ double adjustSpeedSetpoint = speedSetpoint * Math.cos(turnFeedback.getPositionError());
+
+ // Run drive controller
+ double velocityRadPerSec = adjustSpeedSetpoint / WHEEL_RADIUS;
+ io.setDriveVoltage(
+ driveFeedforward.calculate(velocityRadPerSec)
+ + driveFeedback.calculate(inputs.driveVelocityRadPerSec, velocityRadPerSec));
+ }
+ }
+
+ // Calculate position deltas for odometry
+ int deltaCount =
+ Math.min(inputs.odometryDrivePositionsRad.length, inputs.odometryTurnPositions.length);
+ positionDeltas = new SwerveModulePosition[deltaCount];
+ for (int i = 0; i < deltaCount; i++) {
+ double positionMeters = inputs.odometryDrivePositionsRad[i] * WHEEL_RADIUS;
+ Rotation2d angle =
+ inputs.odometryTurnPositions[i].plus(
+ turnRelativeOffset != null ? turnRelativeOffset : new Rotation2d());
+ positionDeltas[i] = new SwerveModulePosition(positionMeters - lastPositionMeters, angle);
+ lastPositionMeters = positionMeters;
+ }
+ }
+
+ /** Runs the module with the specified setpoint state. Returns the optimized state. */
+ public SwerveModuleState runSetpoint(SwerveModuleState state) {
+ // Optimize state based on current angle
+ // Controllers run in "periodic" when the setpoint is not null
+ var optimizedState = SwerveModuleState.optimize(state, getAngle());
+
+ // Update setpoints, controllers run in "periodic"
+ angleSetpoint = optimizedState.angle;
+ speedSetpoint = optimizedState.speedMetersPerSecond;
+
+ return optimizedState;
+ }
+
+ /** Runs the module with the specified voltage while controlling to zero degrees. */
+ public void runCharacterization(double volts) {
+ // Closed loop turn control
+ angleSetpoint = new Rotation2d();
+
+ // Open loop drive control
+ io.setDriveVoltage(volts);
+ speedSetpoint = null;
+ }
+
+ /** Disables all outputs to motors. */
+ public void stop() {
+ io.setTurnVoltage(0.0);
+ io.setDriveVoltage(0.0);
+
+ // Disable closed loop control for turn and drive
+ angleSetpoint = null;
+ speedSetpoint = null;
+ }
+
+ /** Sets whether brake mode is enabled. */
+ public void setBrakeMode(boolean enabled) {
+ io.setDriveBrakeMode(enabled);
+ io.setTurnBrakeMode(enabled);
+ }
+
+ /** Returns the current turn angle of the module. */
+ public Rotation2d getAngle() {
+ if (turnRelativeOffset == null) {
+ return new Rotation2d();
+ } else {
+ return inputs.turnPosition.plus(turnRelativeOffset);
+ }
+ }
+
+ /** Returns the current drive position of the module in meters. */
+ public double getPositionMeters() {
+ return inputs.drivePositionRad * WHEEL_RADIUS;
+ }
+
+ /** Returns the current drive velocity of the module in meters per second. */
+ public double getVelocityMetersPerSec() {
+ return inputs.driveVelocityRadPerSec * WHEEL_RADIUS;
+ }
+
+ /** Returns the module position (turn angle and drive position). */
+ public SwerveModulePosition getPosition() {
+ return new SwerveModulePosition(getPositionMeters(), getAngle());
+ }
+
+ /** Returns the module state (turn angle and drive velocity). */
+ public SwerveModuleState getState() {
+ return new SwerveModuleState(getVelocityMetersPerSec(), getAngle());
+ }
+
+ /** Returns the module position deltas received this cycle. */
+ public SwerveModulePosition[] getPositionDeltas() {
+ return positionDeltas;
+ }
+
+ /** Returns the drive velocity in radians/sec. */
+ public double getCharacterizationVelocity() {
+ return inputs.driveVelocityRadPerSec;
+ }
+}
diff --git a/src/main/java/frc/robot/subsystems/drive/ModuleIO.java b/src/main/java/frc/robot/subsystems/drive/ModuleIO.java
index 8620ae3..e311335 100644
--- a/src/main/java/frc/robot/subsystems/drive/ModuleIO.java
+++ b/src/main/java/frc/robot/subsystems/drive/ModuleIO.java
@@ -1,51 +1,51 @@
-// Copyright 2021-2024 FRC 6328
-// http://github.com/Mechanical-Advantage
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// version 3 as published by the Free Software Foundation or
-// available in the root directory of this project.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-package frc.robot.subsystems.drive;
-
-import edu.wpi.first.math.geometry.Rotation2d;
-import org.littletonrobotics.junction.AutoLog;
-
-public interface ModuleIO {
- @AutoLog
- public static class ModuleIOInputs {
- public double drivePositionRad = 0.0;
- public double driveVelocityRadPerSec = 0.0;
- public double driveAppliedVolts = 0.0;
- public double[] driveCurrentAmps = new double[] {};
-
- public Rotation2d turnAbsolutePosition = new Rotation2d();
- public Rotation2d turnPosition = new Rotation2d();
- public double turnVelocityRadPerSec = 0.0;
- public double turnAppliedVolts = 0.0;
- public double[] turnCurrentAmps = new double[] {};
-
- public double[] odometryDrivePositionsRad = new double[] {};
- public Rotation2d[] odometryTurnPositions = new Rotation2d[] {};
- }
-
- /** Updates the set of loggable inputs. */
- public default void updateInputs(ModuleIOInputs inputs) {}
-
- /** Run the drive motor at the specified voltage. */
- public default void setDriveVoltage(double volts) {}
-
- /** Run the turn motor at the specified voltage. */
- public default void setTurnVoltage(double volts) {}
-
- /** Enable or disable brake mode on the drive motor. */
- public default void setDriveBrakeMode(boolean enable) {}
-
- /** Enable or disable brake mode on the turn motor. */
- public default void setTurnBrakeMode(boolean enable) {}
-}
+// Copyright 2021-2024 FRC 6328
+// http://github.com/Mechanical-Advantage
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 3 as published by the Free Software Foundation or
+// available in the root directory of this project.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+package frc.robot.subsystems.drive;
+
+import edu.wpi.first.math.geometry.Rotation2d;
+import org.littletonrobotics.junction.AutoLog;
+
+public interface ModuleIO {
+ @AutoLog
+ public static class ModuleIOInputs {
+ public double drivePositionRad = 0.0;
+ public double driveVelocityRadPerSec = 0.0;
+ public double driveAppliedVolts = 0.0;
+ public double[] driveCurrentAmps = new double[] {};
+
+ public Rotation2d turnAbsolutePosition = new Rotation2d();
+ public Rotation2d turnPosition = new Rotation2d();
+ public double turnVelocityRadPerSec = 0.0;
+ public double turnAppliedVolts = 0.0;
+ public double[] turnCurrentAmps = new double[] {};
+
+ public double[] odometryDrivePositionsRad = new double[] {};
+ public Rotation2d[] odometryTurnPositions = new Rotation2d[] {};
+ }
+
+ /** Updates the set of loggable inputs. */
+ public default void updateInputs(ModuleIOInputs inputs) {}
+
+ /** Run the drive motor at the specified voltage. */
+ public default void setDriveVoltage(double volts) {}
+
+ /** Run the turn motor at the specified voltage. */
+ public default void setTurnVoltage(double volts) {}
+
+ /** Enable or disable brake mode on the drive motor. */
+ public default void setDriveBrakeMode(boolean enable) {}
+
+ /** Enable or disable brake mode on the turn motor. */
+ public default void setTurnBrakeMode(boolean enable) {}
+}
diff --git a/src/main/java/frc/robot/subsystems/drive/ModuleIOSim.java b/src/main/java/frc/robot/subsystems/drive/ModuleIOSim.java
index c309c68..21a6543 100644
--- a/src/main/java/frc/robot/subsystems/drive/ModuleIOSim.java
+++ b/src/main/java/frc/robot/subsystems/drive/ModuleIOSim.java
@@ -1,70 +1,70 @@
-// Copyright 2021-2024 FRC 6328
-// http://github.com/Mechanical-Advantage
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// version 3 as published by the Free Software Foundation or
-// available in the root directory of this project.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-package frc.robot.subsystems.drive;
-
-import edu.wpi.first.math.MathUtil;
-import edu.wpi.first.math.geometry.Rotation2d;
-import edu.wpi.first.math.system.plant.DCMotor;
-import edu.wpi.first.wpilibj.simulation.DCMotorSim;
-
-/**
- * Physics sim implementation of module IO.
- *
- * Uses two flywheel sims for the drive and turn motors, with the absolute position initialized
- * to a random value. The flywheel sims are not physically accurate, but provide a decent
- * approximation for the behavior of the module.
- */
-public class ModuleIOSim implements ModuleIO {
- private static final double LOOP_PERIOD_SECS = 0.02;
-
- private DCMotorSim driveSim = new DCMotorSim(DCMotor.getNEO(1), 6.75, 0.025);
- private DCMotorSim turnSim = new DCMotorSim(DCMotor.getNEO(1), 150.0 / 7.0, 0.004);
-
- private final Rotation2d turnAbsoluteInitPosition = new Rotation2d(Math.random() * 2.0 * Math.PI);
- private double driveAppliedVolts = 0.0;
- private double turnAppliedVolts = 0.0;
-
- @Override
- public void updateInputs(ModuleIOInputs inputs) {
- driveSim.update(LOOP_PERIOD_SECS);
- turnSim.update(LOOP_PERIOD_SECS);
-
- inputs.drivePositionRad = driveSim.getAngularPositionRad();
- inputs.driveVelocityRadPerSec = driveSim.getAngularVelocityRadPerSec();
- inputs.driveAppliedVolts = driveAppliedVolts;
- inputs.driveCurrentAmps = new double[] {Math.abs(driveSim.getCurrentDrawAmps())};
-
- inputs.turnAbsolutePosition =
- new Rotation2d(turnSim.getAngularPositionRad()).plus(turnAbsoluteInitPosition);
- inputs.turnPosition = new Rotation2d(turnSim.getAngularPositionRad());
- inputs.turnVelocityRadPerSec = turnSim.getAngularVelocityRadPerSec();
- inputs.turnAppliedVolts = turnAppliedVolts;
- inputs.turnCurrentAmps = new double[] {Math.abs(turnSim.getCurrentDrawAmps())};
-
- inputs.odometryDrivePositionsRad = new double[] {inputs.drivePositionRad};
- inputs.odometryTurnPositions = new Rotation2d[] {inputs.turnPosition};
- }
-
- @Override
- public void setDriveVoltage(double volts) {
- driveAppliedVolts = MathUtil.clamp(volts, -12.0, 12.0);
- driveSim.setInputVoltage(driveAppliedVolts);
- }
-
- @Override
- public void setTurnVoltage(double volts) {
- turnAppliedVolts = MathUtil.clamp(volts, -12.0, 12.0);
- turnSim.setInputVoltage(turnAppliedVolts);
- }
-}
+// Copyright 2021-2024 FRC 6328
+// http://github.com/Mechanical-Advantage
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 3 as published by the Free Software Foundation or
+// available in the root directory of this project.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+package frc.robot.subsystems.drive;
+
+import edu.wpi.first.math.MathUtil;
+import edu.wpi.first.math.geometry.Rotation2d;
+import edu.wpi.first.math.system.plant.DCMotor;
+import edu.wpi.first.wpilibj.simulation.DCMotorSim;
+
+/**
+ * Physics sim implementation of module IO.
+ *
+ *
Uses two flywheel sims for the drive and turn motors, with the absolute position initialized
+ * to a random value. The flywheel sims are not physically accurate, but provide a decent
+ * approximation for the behavior of the module.
+ */
+public class ModuleIOSim implements ModuleIO {
+ private static final double LOOP_PERIOD_SECS = 0.02;
+
+ private DCMotorSim driveSim = new DCMotorSim(DCMotor.getNEO(1), 6.75, 0.025);
+ private DCMotorSim turnSim = new DCMotorSim(DCMotor.getNEO(1), 150.0 / 7.0, 0.004);
+
+ private final Rotation2d turnAbsoluteInitPosition = new Rotation2d(Math.random() * 2.0 * Math.PI);
+ private double driveAppliedVolts = 0.0;
+ private double turnAppliedVolts = 0.0;
+
+ @Override
+ public void updateInputs(ModuleIOInputs inputs) {
+ driveSim.update(LOOP_PERIOD_SECS);
+ turnSim.update(LOOP_PERIOD_SECS);
+
+ inputs.drivePositionRad = driveSim.getAngularPositionRad();
+ inputs.driveVelocityRadPerSec = driveSim.getAngularVelocityRadPerSec();
+ inputs.driveAppliedVolts = driveAppliedVolts;
+ inputs.driveCurrentAmps = new double[] {Math.abs(driveSim.getCurrentDrawAmps())};
+
+ inputs.turnAbsolutePosition =
+ new Rotation2d(turnSim.getAngularPositionRad()).plus(turnAbsoluteInitPosition);
+ inputs.turnPosition = new Rotation2d(turnSim.getAngularPositionRad());
+ inputs.turnVelocityRadPerSec = turnSim.getAngularVelocityRadPerSec();
+ inputs.turnAppliedVolts = turnAppliedVolts;
+ inputs.turnCurrentAmps = new double[] {Math.abs(turnSim.getCurrentDrawAmps())};
+
+ inputs.odometryDrivePositionsRad = new double[] {inputs.drivePositionRad};
+ inputs.odometryTurnPositions = new Rotation2d[] {inputs.turnPosition};
+ }
+
+ @Override
+ public void setDriveVoltage(double volts) {
+ driveAppliedVolts = MathUtil.clamp(volts, -12.0, 12.0);
+ driveSim.setInputVoltage(driveAppliedVolts);
+ }
+
+ @Override
+ public void setTurnVoltage(double volts) {
+ turnAppliedVolts = MathUtil.clamp(volts, -12.0, 12.0);
+ turnSim.setInputVoltage(turnAppliedVolts);
+ }
+}
diff --git a/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFX.java b/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFX.java
index 04e0225..bf08788 100644
--- a/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFX.java
+++ b/src/main/java/frc/robot/subsystems/drive/ModuleIOTalonFX.java
@@ -1,191 +1,191 @@
-// Copyright 2021-2024 FRC 6328
-// http://github.com/Mechanical-Advantage
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// version 3 as published by the Free Software Foundation or
-// available in the root directory of this project.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-package frc.robot.subsystems.drive;
-
-import com.ctre.phoenix6.BaseStatusSignal;
-import com.ctre.phoenix6.StatusSignal;
-import com.ctre.phoenix6.configs.CANcoderConfiguration;
-import com.ctre.phoenix6.configs.MotorOutputConfigs;
-import com.ctre.phoenix6.configs.TalonFXConfiguration;
-import com.ctre.phoenix6.controls.VoltageOut;
-import com.ctre.phoenix6.hardware.CANcoder;
-import com.ctre.phoenix6.hardware.TalonFX;
-import com.ctre.phoenix6.signals.InvertedValue;
-import com.ctre.phoenix6.signals.NeutralModeValue;
-import edu.wpi.first.math.geometry.Rotation2d;
-import edu.wpi.first.math.util.Units;
-import frc.robot.Constants.DriveConstants;
-import java.util.Queue;
-
-/**
- * Module IO implementation for Talon FX drive motor controller, Talon FX turn motor controller, and
- * CANcoder
- *
- *
NOTE: This implementation should be used as a starting point and adapted to different hardware
- * configurations (e.g. If using an analog encoder, copy from "ModuleIOSparkMax")
- *
- *
To calibrate the absolute encoder offsets, point the modules straight (such that forward
- * motion on the drive motor will propel the robot forward) and copy the reported values from the
- * absolute encoders using AdvantageScope. These values are logged under
- * "/Drive/ModuleX/TurnAbsolutePositionRad"
- */
-public class ModuleIOTalonFX implements ModuleIO {
- private final TalonFX driveTalon;
- private final TalonFX turnTalon;
- private final CANcoder cancoder;
-
- private final StatusSignal drivePosition;
- private final Queue drivePositionQueue;
- private final StatusSignal driveVelocity;
- private final StatusSignal driveAppliedVolts;
- private final StatusSignal driveCurrent;
-
- private final StatusSignal turnAbsolutePosition;
- private final StatusSignal turnPosition;
- private final Queue turnPositionQueue;
- private final StatusSignal turnVelocity;
- private final StatusSignal turnAppliedVolts;
- private final StatusSignal turnCurrent;
-
- // Gear ratios for SDS MK4i L2, adjust as necessary
- private final double DRIVE_GEAR_RATIO = (50.0 / 14.0) * (17.0 / 27.0) * (45.0 / 15.0);
- private final double TURN_GEAR_RATIO = 150.0 / 7.0;
-
- private final boolean isTurnMotorInverted = true;
- private final Rotation2d absoluteEncoderOffset;
-
- public ModuleIOTalonFX(int index) {
- if (index >= 4) {
- throw new RuntimeException("Invalid module index");
- }
- driveTalon = new TalonFX(DriveConstants.driveCanIds[index]);
- turnTalon = new TalonFX(DriveConstants.turnCanIds[index]);
- cancoder = new CANcoder(DriveConstants.canCoderIds[index]);
- absoluteEncoderOffset = Rotation2d.fromDegrees(DriveConstants.moduleAngles[index]);
-
- var driveConfig = new TalonFXConfiguration();
- driveConfig.CurrentLimits.StatorCurrentLimit = 40.0;
- driveConfig.CurrentLimits.StatorCurrentLimitEnable = true;
- driveTalon.getConfigurator().apply(driveConfig);
- setDriveBrakeMode(true);
-
- var turnConfig = new TalonFXConfiguration();
- turnConfig.CurrentLimits.StatorCurrentLimit = 30.0;
- turnConfig.CurrentLimits.StatorCurrentLimitEnable = true;
- turnTalon.getConfigurator().apply(turnConfig);
- setTurnBrakeMode(true);
-
- cancoder.getConfigurator().apply(new CANcoderConfiguration());
-
- drivePosition = driveTalon.getPosition();
- drivePositionQueue =
- PhoenixOdometryThread.getInstance().registerSignal(driveTalon, driveTalon.getPosition());
- driveVelocity = driveTalon.getVelocity();
- driveAppliedVolts = driveTalon.getMotorVoltage();
- driveCurrent = driveTalon.getStatorCurrent();
-
- turnAbsolutePosition = cancoder.getAbsolutePosition();
- turnPosition = turnTalon.getPosition();
- turnPositionQueue =
- PhoenixOdometryThread.getInstance().registerSignal(turnTalon, turnTalon.getPosition());
- turnVelocity = turnTalon.getVelocity();
- turnAppliedVolts = turnTalon.getMotorVoltage();
- turnCurrent = turnTalon.getStatorCurrent();
-
- BaseStatusSignal.setUpdateFrequencyForAll(
- Module.ODOMETRY_FREQUENCY, drivePosition, turnPosition);
- BaseStatusSignal.setUpdateFrequencyForAll(
- 50.0,
- driveVelocity,
- driveAppliedVolts,
- driveCurrent,
- turnAbsolutePosition,
- turnVelocity,
- turnAppliedVolts,
- turnCurrent);
- driveTalon.optimizeBusUtilization();
- turnTalon.optimizeBusUtilization();
- }
-
- @Override
- public void updateInputs(ModuleIOInputs inputs) {
- BaseStatusSignal.refreshAll(
- drivePosition,
- driveVelocity,
- driveAppliedVolts,
- driveCurrent,
- turnAbsolutePosition,
- turnPosition,
- turnVelocity,
- turnAppliedVolts,
- turnCurrent);
-
- inputs.drivePositionRad =
- Units.rotationsToRadians(drivePosition.getValueAsDouble()) / DRIVE_GEAR_RATIO;
- inputs.driveVelocityRadPerSec =
- Units.rotationsToRadians(driveVelocity.getValueAsDouble()) / DRIVE_GEAR_RATIO;
- inputs.driveAppliedVolts = driveAppliedVolts.getValueAsDouble();
- inputs.driveCurrentAmps = new double[] {driveCurrent.getValueAsDouble()};
-
- inputs.turnAbsolutePosition =
- Rotation2d.fromRotations(turnAbsolutePosition.getValueAsDouble())
- .minus(absoluteEncoderOffset);
- inputs.turnPosition =
- Rotation2d.fromRotations(turnPosition.getValueAsDouble() / TURN_GEAR_RATIO);
- inputs.turnVelocityRadPerSec =
- Units.rotationsToRadians(turnVelocity.getValueAsDouble()) / TURN_GEAR_RATIO;
- inputs.turnAppliedVolts = turnAppliedVolts.getValueAsDouble();
- inputs.turnCurrentAmps = new double[] {turnCurrent.getValueAsDouble()};
-
- inputs.odometryDrivePositionsRad =
- drivePositionQueue.stream()
- .mapToDouble((Double value) -> Units.rotationsToRadians(value) / DRIVE_GEAR_RATIO)
- .toArray();
- inputs.odometryTurnPositions =
- turnPositionQueue.stream()
- .map((Double value) -> Rotation2d.fromRotations(value / TURN_GEAR_RATIO))
- .toArray(Rotation2d[]::new);
- drivePositionQueue.clear();
- turnPositionQueue.clear();
- }
-
- @Override
- public void setDriveVoltage(double volts) {
- driveTalon.setControl(new VoltageOut(volts));
- }
-
- @Override
- public void setTurnVoltage(double volts) {
- turnTalon.setControl(new VoltageOut(volts));
- }
-
- @Override
- public void setDriveBrakeMode(boolean enable) {
- var config = new MotorOutputConfigs();
- config.Inverted = InvertedValue.CounterClockwise_Positive;
- config.NeutralMode = enable ? NeutralModeValue.Brake : NeutralModeValue.Coast;
- driveTalon.getConfigurator().apply(config);
- }
-
- @Override
- public void setTurnBrakeMode(boolean enable) {
- var config = new MotorOutputConfigs();
- config.Inverted =
- isTurnMotorInverted
- ? InvertedValue.Clockwise_Positive
- : InvertedValue.CounterClockwise_Positive;
- config.NeutralMode = enable ? NeutralModeValue.Brake : NeutralModeValue.Coast;
- turnTalon.getConfigurator().apply(config);
- }
-}
+// Copyright 2021-2024 FRC 6328
+// http://github.com/Mechanical-Advantage
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 3 as published by the Free Software Foundation or
+// available in the root directory of this project.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+package frc.robot.subsystems.drive;
+
+import com.ctre.phoenix6.BaseStatusSignal;
+import com.ctre.phoenix6.StatusSignal;
+import com.ctre.phoenix6.configs.CANcoderConfiguration;
+import com.ctre.phoenix6.configs.MotorOutputConfigs;
+import com.ctre.phoenix6.configs.TalonFXConfiguration;
+import com.ctre.phoenix6.controls.VoltageOut;
+import com.ctre.phoenix6.hardware.CANcoder;
+import com.ctre.phoenix6.hardware.TalonFX;
+import com.ctre.phoenix6.signals.InvertedValue;
+import com.ctre.phoenix6.signals.NeutralModeValue;
+import edu.wpi.first.math.geometry.Rotation2d;
+import edu.wpi.first.math.util.Units;
+import frc.robot.Constants.DriveConstants;
+import java.util.Queue;
+
+/**
+ * Module IO implementation for Talon FX drive motor controller, Talon FX turn motor controller, and
+ * CANcoder
+ *
+ * NOTE: This implementation should be used as a starting point and adapted to different hardware
+ * configurations (e.g. If using an analog encoder, copy from "ModuleIOSparkMax")
+ *
+ *
To calibrate the absolute encoder offsets, point the modules straight (such that forward
+ * motion on the drive motor will propel the robot forward) and copy the reported values from the
+ * absolute encoders using AdvantageScope. These values are logged under
+ * "/Drive/ModuleX/TurnAbsolutePositionRad"
+ */
+public class ModuleIOTalonFX implements ModuleIO {
+ private final TalonFX driveTalon;
+ private final TalonFX turnTalon;
+ private final CANcoder cancoder;
+
+ private final StatusSignal drivePosition;
+ private final Queue drivePositionQueue;
+ private final StatusSignal driveVelocity;
+ private final StatusSignal driveAppliedVolts;
+ private final StatusSignal driveCurrent;
+
+ private final StatusSignal turnAbsolutePosition;
+ private final StatusSignal turnPosition;
+ private final Queue turnPositionQueue;
+ private final StatusSignal turnVelocity;
+ private final StatusSignal turnAppliedVolts;
+ private final StatusSignal turnCurrent;
+
+ // Gear ratios for SDS MK4i L2, adjust as necessary
+ private final double DRIVE_GEAR_RATIO = (50.0 / 14.0) * (17.0 / 27.0) * (45.0 / 15.0);
+ private final double TURN_GEAR_RATIO = 150.0 / 7.0;
+
+ private final boolean isTurnMotorInverted = true;
+ private final Rotation2d absoluteEncoderOffset;
+
+ public ModuleIOTalonFX(int index) {
+ if (index >= 4) {
+ throw new RuntimeException("Invalid module index");
+ }
+ driveTalon = new TalonFX(DriveConstants.driveCanIds[index]);
+ turnTalon = new TalonFX(DriveConstants.turnCanIds[index]);
+ cancoder = new CANcoder(DriveConstants.canCoderIds[index]);
+ absoluteEncoderOffset = Rotation2d.fromDegrees(DriveConstants.moduleAngles[index]);
+
+ var driveConfig = new TalonFXConfiguration();
+ driveConfig.CurrentLimits.StatorCurrentLimit = 40.0;
+ driveConfig.CurrentLimits.StatorCurrentLimitEnable = true;
+ driveTalon.getConfigurator().apply(driveConfig);
+ setDriveBrakeMode(true);
+
+ var turnConfig = new TalonFXConfiguration();
+ turnConfig.CurrentLimits.StatorCurrentLimit = 30.0;
+ turnConfig.CurrentLimits.StatorCurrentLimitEnable = true;
+ turnTalon.getConfigurator().apply(turnConfig);
+ setTurnBrakeMode(true);
+
+ cancoder.getConfigurator().apply(new CANcoderConfiguration());
+
+ drivePosition = driveTalon.getPosition();
+ drivePositionQueue =
+ PhoenixOdometryThread.getInstance().registerSignal(driveTalon, driveTalon.getPosition());
+ driveVelocity = driveTalon.getVelocity();
+ driveAppliedVolts = driveTalon.getMotorVoltage();
+ driveCurrent = driveTalon.getStatorCurrent();
+
+ turnAbsolutePosition = cancoder.getAbsolutePosition();
+ turnPosition = turnTalon.getPosition();
+ turnPositionQueue =
+ PhoenixOdometryThread.getInstance().registerSignal(turnTalon, turnTalon.getPosition());
+ turnVelocity = turnTalon.getVelocity();
+ turnAppliedVolts = turnTalon.getMotorVoltage();
+ turnCurrent = turnTalon.getStatorCurrent();
+
+ BaseStatusSignal.setUpdateFrequencyForAll(
+ Module.ODOMETRY_FREQUENCY, drivePosition, turnPosition);
+ BaseStatusSignal.setUpdateFrequencyForAll(
+ 50.0,
+ driveVelocity,
+ driveAppliedVolts,
+ driveCurrent,
+ turnAbsolutePosition,
+ turnVelocity,
+ turnAppliedVolts,
+ turnCurrent);
+ driveTalon.optimizeBusUtilization();
+ turnTalon.optimizeBusUtilization();
+ }
+
+ @Override
+ public void updateInputs(ModuleIOInputs inputs) {
+ BaseStatusSignal.refreshAll(
+ drivePosition,
+ driveVelocity,
+ driveAppliedVolts,
+ driveCurrent,
+ turnAbsolutePosition,
+ turnPosition,
+ turnVelocity,
+ turnAppliedVolts,
+ turnCurrent);
+
+ inputs.drivePositionRad =
+ Units.rotationsToRadians(drivePosition.getValueAsDouble()) / DRIVE_GEAR_RATIO;
+ inputs.driveVelocityRadPerSec =
+ Units.rotationsToRadians(driveVelocity.getValueAsDouble()) / DRIVE_GEAR_RATIO;
+ inputs.driveAppliedVolts = driveAppliedVolts.getValueAsDouble();
+ inputs.driveCurrentAmps = new double[] {driveCurrent.getValueAsDouble()};
+
+ inputs.turnAbsolutePosition =
+ Rotation2d.fromRotations(turnAbsolutePosition.getValueAsDouble())
+ .minus(absoluteEncoderOffset);
+ inputs.turnPosition =
+ Rotation2d.fromRotations(turnPosition.getValueAsDouble() / TURN_GEAR_RATIO);
+ inputs.turnVelocityRadPerSec =
+ Units.rotationsToRadians(turnVelocity.getValueAsDouble()) / TURN_GEAR_RATIO;
+ inputs.turnAppliedVolts = turnAppliedVolts.getValueAsDouble();
+ inputs.turnCurrentAmps = new double[] {turnCurrent.getValueAsDouble()};
+
+ inputs.odometryDrivePositionsRad =
+ drivePositionQueue.stream()
+ .mapToDouble((Double value) -> Units.rotationsToRadians(value) / DRIVE_GEAR_RATIO)
+ .toArray();
+ inputs.odometryTurnPositions =
+ turnPositionQueue.stream()
+ .map((Double value) -> Rotation2d.fromRotations(value / TURN_GEAR_RATIO))
+ .toArray(Rotation2d[]::new);
+ drivePositionQueue.clear();
+ turnPositionQueue.clear();
+ }
+
+ @Override
+ public void setDriveVoltage(double volts) {
+ driveTalon.setControl(new VoltageOut(volts));
+ }
+
+ @Override
+ public void setTurnVoltage(double volts) {
+ turnTalon.setControl(new VoltageOut(volts));
+ }
+
+ @Override
+ public void setDriveBrakeMode(boolean enable) {
+ var config = new MotorOutputConfigs();
+ config.Inverted = InvertedValue.CounterClockwise_Positive;
+ config.NeutralMode = enable ? NeutralModeValue.Brake : NeutralModeValue.Coast;
+ driveTalon.getConfigurator().apply(config);
+ }
+
+ @Override
+ public void setTurnBrakeMode(boolean enable) {
+ var config = new MotorOutputConfigs();
+ config.Inverted =
+ isTurnMotorInverted
+ ? InvertedValue.Clockwise_Positive
+ : InvertedValue.CounterClockwise_Positive;
+ config.NeutralMode = enable ? NeutralModeValue.Brake : NeutralModeValue.Coast;
+ turnTalon.getConfigurator().apply(config);
+ }
+}
diff --git a/src/main/java/frc/robot/subsystems/drive/PhoenixOdometryThread.java b/src/main/java/frc/robot/subsystems/drive/PhoenixOdometryThread.java
index 33a4448..8c1ed0c 100644
--- a/src/main/java/frc/robot/subsystems/drive/PhoenixOdometryThread.java
+++ b/src/main/java/frc/robot/subsystems/drive/PhoenixOdometryThread.java
@@ -1,108 +1,108 @@
-// Copyright 2021-2024 FRC 6328
-// http://github.com/Mechanical-Advantage
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// version 3 as published by the Free Software Foundation or
-// available in the root directory of this project.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-package frc.robot.subsystems.drive;
-
-import com.ctre.phoenix6.BaseStatusSignal;
-import com.ctre.phoenix6.CANBus;
-import com.ctre.phoenix6.StatusSignal;
-import com.ctre.phoenix6.hardware.ParentDevice;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Queue;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * Provides an interface for asynchronously reading high-frequency measurements to a set of queues.
- *
- * This version is intended for Phoenix 6 devices on both the RIO and CANivore buses. When using
- * a CANivore, the thread uses the "waitForAll" blocking method to enable more consistent sampling.
- * This also allows Phoenix Pro users to benefit from lower latency between devices using CANivore
- * time synchronization.
- */
-public class PhoenixOdometryThread extends Thread {
- private final Lock signalsLock =
- new ReentrantLock(); // Prevents conflicts when registering signals
- private BaseStatusSignal[] signals = new BaseStatusSignal[0];
- private final List> queues = new ArrayList<>();
- private boolean isCANFD = false;
-
- private static PhoenixOdometryThread instance = null;
-
- public static PhoenixOdometryThread getInstance() {
- if (instance == null) {
- instance = new PhoenixOdometryThread();
- }
- return instance;
- }
-
- private PhoenixOdometryThread() {
- setName("PhoenixOdometryThread");
- setDaemon(true);
- start();
- }
-
- public Queue registerSignal(ParentDevice device, StatusSignal signal) {
- Queue queue = new ArrayBlockingQueue<>(100);
- signalsLock.lock();
- Drive.odometryLock.lock();
- try {
- isCANFD = CANBus.isNetworkFD(device.getNetwork());
- BaseStatusSignal[] newSignals = new BaseStatusSignal[signals.length + 1];
- System.arraycopy(signals, 0, newSignals, 0, signals.length);
- newSignals[signals.length] = signal;
- signals = newSignals;
- queues.add(queue);
- } finally {
- signalsLock.unlock();
- Drive.odometryLock.unlock();
- }
- return queue;
- }
-
- @Override
- public void run() {
- while (true) {
- // Wait for updates from all signals
- signalsLock.lock();
- try {
- if (isCANFD) {
- BaseStatusSignal.waitForAll(2.0 / Module.ODOMETRY_FREQUENCY, signals);
- } else {
- // "waitForAll" does not support blocking on multiple
- // signals with a bus that is not CAN FD, regardless
- // of Pro licensing. No reasoning for this behavior
- // is provided by the documentation.
- Thread.sleep((long) (1000.0 / Module.ODOMETRY_FREQUENCY));
- if (signals.length > 0) BaseStatusSignal.refreshAll(signals);
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- } finally {
- signalsLock.unlock();
- }
-
- // Save new data to queues
- Drive.odometryLock.lock();
- try {
- for (int i = 0; i < signals.length; i++) {
- queues.get(i).offer(signals[i].getValueAsDouble());
- }
- } finally {
- Drive.odometryLock.unlock();
- }
- }
- }
-}
+// Copyright 2021-2024 FRC 6328
+// http://github.com/Mechanical-Advantage
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 3 as published by the Free Software Foundation or
+// available in the root directory of this project.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+package frc.robot.subsystems.drive;
+
+import com.ctre.phoenix6.BaseStatusSignal;
+import com.ctre.phoenix6.CANBus;
+import com.ctre.phoenix6.StatusSignal;
+import com.ctre.phoenix6.hardware.ParentDevice;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Provides an interface for asynchronously reading high-frequency measurements to a set of queues.
+ *
+ * This version is intended for Phoenix 6 devices on both the RIO and CANivore buses. When using
+ * a CANivore, the thread uses the "waitForAll" blocking method to enable more consistent sampling.
+ * This also allows Phoenix Pro users to benefit from lower latency between devices using CANivore
+ * time synchronization.
+ */
+public class PhoenixOdometryThread extends Thread {
+ private final Lock signalsLock =
+ new ReentrantLock(); // Prevents conflicts when registering signals
+ private BaseStatusSignal[] signals = new BaseStatusSignal[0];
+ private final List> queues = new ArrayList<>();
+ private boolean isCANFD = false;
+
+ private static PhoenixOdometryThread instance = null;
+
+ public static PhoenixOdometryThread getInstance() {
+ if (instance == null) {
+ instance = new PhoenixOdometryThread();
+ }
+ return instance;
+ }
+
+ private PhoenixOdometryThread() {
+ setName("PhoenixOdometryThread");
+ setDaemon(true);
+ start();
+ }
+
+ public Queue registerSignal(ParentDevice device, StatusSignal signal) {
+ Queue queue = new ArrayBlockingQueue<>(100);
+ signalsLock.lock();
+ Drive.odometryLock.lock();
+ try {
+ isCANFD = CANBus.isNetworkFD(device.getNetwork());
+ BaseStatusSignal[] newSignals = new BaseStatusSignal[signals.length + 1];
+ System.arraycopy(signals, 0, newSignals, 0, signals.length);
+ newSignals[signals.length] = signal;
+ signals = newSignals;
+ queues.add(queue);
+ } finally {
+ signalsLock.unlock();
+ Drive.odometryLock.unlock();
+ }
+ return queue;
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ // Wait for updates from all signals
+ signalsLock.lock();
+ try {
+ if (isCANFD) {
+ BaseStatusSignal.waitForAll(2.0 / Module.ODOMETRY_FREQUENCY, signals);
+ } else {
+ // "waitForAll" does not support blocking on multiple
+ // signals with a bus that is not CAN FD, regardless
+ // of Pro licensing. No reasoning for this behavior
+ // is provided by the documentation.
+ Thread.sleep((long) (1000.0 / Module.ODOMETRY_FREQUENCY));
+ if (signals.length > 0) BaseStatusSignal.refreshAll(signals);
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } finally {
+ signalsLock.unlock();
+ }
+
+ // Save new data to queues
+ Drive.odometryLock.lock();
+ try {
+ for (int i = 0; i < signals.length; i++) {
+ queues.get(i).offer(signals[i].getValueAsDouble());
+ }
+ } finally {
+ Drive.odometryLock.unlock();
+ }
+ }
+ }
+}
diff --git a/src/main/java/frc/robot/subsystems/intake/Intake.java b/src/main/java/frc/robot/subsystems/intake/Intake.java
index 53982ec..9b508c1 100644
--- a/src/main/java/frc/robot/subsystems/intake/Intake.java
+++ b/src/main/java/frc/robot/subsystems/intake/Intake.java
@@ -1,38 +1,38 @@
-package frc.robot.subsystems.intake;
-
-import edu.wpi.first.wpilibj2.command.Command;
-import edu.wpi.first.wpilibj2.command.InstantCommand;
-import edu.wpi.first.wpilibj2.command.SubsystemBase;
-import frc.robot.Constants.IntakeConstants;
-import org.littletonrobotics.junction.Logger;
-
-public class Intake extends SubsystemBase {
- public final IntakeIO io;
- public final IntakeIOInputsAutoLogged inputs = new IntakeIOInputsAutoLogged();
-
- public Intake(IntakeIO io) {
- this.io = io;
- }
-
- @Override
- public void periodic() {
- io.updateInputs(inputs);
- Logger.processInputs("Intake", inputs);
- }
-
- public void on() {
- io.setPower(IntakeConstants.intakeOnPower);
- }
-
- public void off() {
- io.setPower(0.0);
- }
-
- public Command onCommand() {
- return new InstantCommand(this::on, this);
- }
-
- public Command offCommand() {
- return new InstantCommand(this::off, this);
- }
-}
+package frc.robot.subsystems.intake;
+
+import edu.wpi.first.wpilibj2.command.Command;
+import edu.wpi.first.wpilibj2.command.InstantCommand;
+import edu.wpi.first.wpilibj2.command.SubsystemBase;
+import frc.robot.Constants.IntakeConstants;
+import org.littletonrobotics.junction.Logger;
+
+public class Intake extends SubsystemBase {
+ public final IntakeIO io;
+ public final IntakeIOInputsAutoLogged inputs = new IntakeIOInputsAutoLogged();
+
+ public Intake(IntakeIO io) {
+ this.io = io;
+ }
+
+ @Override
+ public void periodic() {
+ io.updateInputs(inputs);
+ Logger.processInputs("Intake", inputs);
+ }
+
+ public void on() {
+ io.setPower(IntakeConstants.intakeOnPower);
+ }
+
+ public void off() {
+ io.setPower(0.0);
+ }
+
+ public Command onCommand() {
+ return new InstantCommand(this::on, this);
+ }
+
+ public Command offCommand() {
+ return new InstantCommand(this::off, this);
+ }
+}
diff --git a/src/main/java/frc/robot/subsystems/intake/IntakeIO.java b/src/main/java/frc/robot/subsystems/intake/IntakeIO.java
index ecf8915..dcc8dd0 100644
--- a/src/main/java/frc/robot/subsystems/intake/IntakeIO.java
+++ b/src/main/java/frc/robot/subsystems/intake/IntakeIO.java
@@ -1,16 +1,16 @@
-package frc.robot.subsystems.intake;
-
-import org.littletonrobotics.junction.AutoLog;
-
-public interface IntakeIO {
- @AutoLog
- public static class IntakeIOInputs {
- public double current = 0.0;
- }
-
- public default void updateInputs(IntakeIOInputs inputs) {}
-
- public default void setPower(double power) {}
-
- public default void setVoltage(double voltage) {}
-}
+package frc.robot.subsystems.intake;
+
+import org.littletonrobotics.junction.AutoLog;
+
+public interface IntakeIO {
+ @AutoLog
+ public static class IntakeIOInputs {
+ public double current = 0.0;
+ }
+
+ public default void updateInputs(IntakeIOInputs inputs) {}
+
+ public default void setPower(double power) {}
+
+ public default void setVoltage(double voltage) {}
+}
diff --git a/src/main/java/frc/robot/subsystems/intake/IntakeIOReal.java b/src/main/java/frc/robot/subsystems/intake/IntakeIOReal.java
index 89cfb3d..fe3ea92 100644
--- a/src/main/java/frc/robot/subsystems/intake/IntakeIOReal.java
+++ b/src/main/java/frc/robot/subsystems/intake/IntakeIOReal.java
@@ -1,28 +1,28 @@
-package frc.robot.subsystems.intake;
-
-import com.revrobotics.CANSparkLowLevel.MotorType;
-import com.revrobotics.CANSparkMax;
-import frc.robot.Constants.IntakeConstants;
-
-public class IntakeIOReal implements IntakeIO {
- private final CANSparkMax motor;
-
- public IntakeIOReal() {
- motor = new CANSparkMax(IntakeConstants.intakeCANId, MotorType.kBrushless);
- }
-
- @Override
- public void updateInputs(IntakeIO.IntakeIOInputs inputs) {
- inputs.current = motor.getOutputCurrent();
- }
-
- @Override
- public void setPower(double power) {
- motor.set(power);
- }
-
- @Override
- public void setVoltage(double voltage) {
- motor.setVoltage(voltage);
- }
-}
+package frc.robot.subsystems.intake;
+
+import com.revrobotics.CANSparkLowLevel.MotorType;
+import com.revrobotics.CANSparkMax;
+import frc.robot.Constants.IntakeConstants;
+
+public class IntakeIOReal implements IntakeIO {
+ private final CANSparkMax motor;
+
+ public IntakeIOReal() {
+ motor = new CANSparkMax(IntakeConstants.intakeCANId, MotorType.kBrushless);
+ }
+
+ @Override
+ public void updateInputs(IntakeIO.IntakeIOInputs inputs) {
+ inputs.current = motor.getOutputCurrent();
+ }
+
+ @Override
+ public void setPower(double power) {
+ motor.set(power);
+ }
+
+ @Override
+ public void setVoltage(double voltage) {
+ motor.setVoltage(voltage);
+ }
+}
diff --git a/src/main/java/frc/robot/subsystems/intake/IntakeIOSim.java b/src/main/java/frc/robot/subsystems/intake/IntakeIOSim.java
index 4fb3864..4704763 100644
--- a/src/main/java/frc/robot/subsystems/intake/IntakeIOSim.java
+++ b/src/main/java/frc/robot/subsystems/intake/IntakeIOSim.java
@@ -1,4 +1,4 @@
-package frc.robot.subsystems.intake;
-
-// TODO
-public class IntakeIOSim implements IntakeIO {}
+package frc.robot.subsystems.intake;
+
+// TODO
+public class IntakeIOSim implements IntakeIO {}
diff --git a/src/main/java/frc/robot/subsystems/pivot/Pivot.java b/src/main/java/frc/robot/subsystems/pivot/Pivot.java
index 7f53cc3..df80d73 100644
--- a/src/main/java/frc/robot/subsystems/pivot/Pivot.java
+++ b/src/main/java/frc/robot/subsystems/pivot/Pivot.java
@@ -1,42 +1,42 @@
-package frc.robot.subsystems.pivot;
-
-import edu.wpi.first.math.geometry.Rotation2d;
-import edu.wpi.first.wpilibj2.command.SubsystemBase;
-import frc.robot.Constants.PivotConstants;
-import org.littletonrobotics.junction.Logger;
-
-public class Pivot extends SubsystemBase {
- private final PivotIO io;
- private final PivotIOInputsAutoLogged inputs = new PivotIOInputsAutoLogged();
-
- public Pivot(PivotIO io) {
- this.io = io;
- }
-
- public void setTargetPosition(Rotation2d target) {
- if (target.getRadians() < PivotConstants.pivotStart.getRadians()) {
- target = PivotConstants.pivotStart;
- }
-
- if (target.getRadians() > PivotConstants.pivotEnd.getRadians()) {
- target = PivotConstants.pivotEnd;
- }
-
- // surely this isnt necessary
- if (target.getRadians() < PivotConstants.pivotStart.getRadians()
- || target.getRadians() > PivotConstants.pivotEnd.getRadians()) {
- throw new IllegalArgumentException("Target position is out of bounds");
- }
- io.setTargetPosition(target);
- }
-
- public Rotation2d getCurrentPosition() {
- return inputs.pivotCurentAngle;
- }
-
- @Override
- public void periodic() {
- io.updateInputs(inputs);
- Logger.processInputs("Pivot", inputs);
- }
-}
+package frc.robot.subsystems.pivot;
+
+import edu.wpi.first.math.geometry.Rotation2d;
+import edu.wpi.first.wpilibj2.command.SubsystemBase;
+import frc.robot.Constants.PivotConstants;
+import org.littletonrobotics.junction.Logger;
+
+public class Pivot extends SubsystemBase {
+ private final PivotIO io;
+ private final PivotIOInputsAutoLogged inputs = new PivotIOInputsAutoLogged();
+
+ public Pivot(PivotIO io) {
+ this.io = io;
+ }
+
+ public void setTargetPosition(Rotation2d target) {
+ if (target.getRadians() < PivotConstants.pivotStart.getRadians()) {
+ target = PivotConstants.pivotStart;
+ }
+
+ if (target.getRadians() > PivotConstants.pivotEnd.getRadians()) {
+ target = PivotConstants.pivotEnd;
+ }
+
+ // surely this isnt necessary
+ if (target.getRadians() < PivotConstants.pivotStart.getRadians()
+ || target.getRadians() > PivotConstants.pivotEnd.getRadians()) {
+ throw new IllegalArgumentException("Target position is out of bounds");
+ }
+ io.setTargetPosition(target);
+ }
+
+ public Rotation2d getCurrentPosition() {
+ return inputs.pivotCurentAngle;
+ }
+
+ @Override
+ public void periodic() {
+ io.updateInputs(inputs);
+ Logger.processInputs("Pivot", inputs);
+ }
+}
diff --git a/src/main/java/frc/robot/subsystems/pivot/PivotIO.java b/src/main/java/frc/robot/subsystems/pivot/PivotIO.java
index 2d35b9a..22f177e 100644
--- a/src/main/java/frc/robot/subsystems/pivot/PivotIO.java
+++ b/src/main/java/frc/robot/subsystems/pivot/PivotIO.java
@@ -1,16 +1,16 @@
-package frc.robot.subsystems.pivot;
-
-import edu.wpi.first.math.geometry.Rotation2d;
-import org.littletonrobotics.junction.AutoLog;
-
-public interface PivotIO {
- @AutoLog
- public static class PivotIOInputs {
- public Rotation2d pivotCurentAngle = new Rotation2d();
- public Rotation2d pivotTargetAngle = new Rotation2d();
- }
-
- default void updateInputs(PivotIOInputs inputs) {}
-
- default void setTargetPosition(Rotation2d target) {}
-}
+package frc.robot.subsystems.pivot;
+
+import edu.wpi.first.math.geometry.Rotation2d;
+import org.littletonrobotics.junction.AutoLog;
+
+public interface PivotIO {
+ @AutoLog
+ public static class PivotIOInputs {
+ public Rotation2d pivotCurentAngle = new Rotation2d();
+ public Rotation2d pivotTargetAngle = new Rotation2d();
+ }
+
+ default void updateInputs(PivotIOInputs inputs) {}
+
+ default void setTargetPosition(Rotation2d target) {}
+}
diff --git a/src/main/java/frc/robot/subsystems/pivot/PivotIOReal.java b/src/main/java/frc/robot/subsystems/pivot/PivotIOReal.java
index 188f7d2..659662b 100644
--- a/src/main/java/frc/robot/subsystems/pivot/PivotIOReal.java
+++ b/src/main/java/frc/robot/subsystems/pivot/PivotIOReal.java
@@ -1,76 +1,76 @@
-package frc.robot.subsystems.pivot;
-
-import com.ctre.phoenix6.BaseStatusSignal;
-import com.ctre.phoenix6.StatusSignal;
-import com.ctre.phoenix6.configs.Slot0Configs;
-import com.ctre.phoenix6.configs.TalonFXConfiguration;
-import com.ctre.phoenix6.hardware.TalonFX;
-import com.ctre.phoenix6.signals.NeutralModeValue;
-import edu.wpi.first.math.geometry.Rotation2d;
-import frc.robot.Constants.PivotConstants;
-
-public class PivotIOReal implements PivotIO {
- private final TalonFX pivotMotor;
- // in rotations!!
- private final StatusSignal position;
- // in rotations!!
- double zeroPosition;
- Rotation2d targetPosition;
- TalonFXConfiguration config;
-
- public PivotIOReal() {
- pivotMotor = new TalonFX(PivotConstants.pivotCANId);
-
- config = new TalonFXConfiguration();
-
- config.CurrentLimits.SupplyCurrentLimit = 30;
- config.CurrentLimits.SupplyCurrentLimitEnable = true;
- config.MotorOutput.NeutralMode = NeutralModeValue.Brake;
- config.Slot0 =
- new Slot0Configs()
- .withKP(PivotConstants.p)
- .withKI(PivotConstants.i)
- .withKD(PivotConstants.d);
-
- pivotMotor.getConfigurator().apply(config);
-
- // in rotations!!
- position = pivotMotor.getPosition();
-
- BaseStatusSignal.setUpdateFrequencyForAll(20.0, position);
- pivotMotor.optimizeBusUtilization(1.0);
-
- // PivotConstants.pivotStart
- zeroPosition = position.getValueAsDouble();
- targetPosition = angleFromEncoder(zeroPosition);
- }
-
- public void updateInputs(PivotIOInputs inputs) {
- BaseStatusSignal.refreshAll(position);
- double currentPosition = position.getValueAsDouble();
-
- inputs.pivotCurentAngle = angleFromEncoder(currentPosition);
- inputs.pivotTargetAngle = targetPosition;
- }
-
- /** sets the target position where 0 is facing towards the back of the robot */
- public void setTargetPosition(Rotation2d target) {
- targetPosition = target;
- pivotMotor.setPosition(encoderFromAngle(target));
- }
-
- private Rotation2d angleFromEncoder(double encoderTicks) {
- // 2048 ticks per rotation
- var delta =
- Rotation2d.fromRotations((encoderTicks - zeroPosition) / PivotConstants.pivotGearRatio);
-
- return delta.plus(PivotConstants.pivotStart);
- }
-
- private double encoderFromAngle(Rotation2d angle) {
- var delta =
- angle.minus(PivotConstants.pivotStart).getRotations() * PivotConstants.pivotGearRatio;
-
- return delta + zeroPosition;
- }
-}
+package frc.robot.subsystems.pivot;
+
+import com.ctre.phoenix6.BaseStatusSignal;
+import com.ctre.phoenix6.StatusSignal;
+import com.ctre.phoenix6.configs.Slot0Configs;
+import com.ctre.phoenix6.configs.TalonFXConfiguration;
+import com.ctre.phoenix6.hardware.TalonFX;
+import com.ctre.phoenix6.signals.NeutralModeValue;
+import edu.wpi.first.math.geometry.Rotation2d;
+import frc.robot.Constants.PivotConstants;
+
+public class PivotIOReal implements PivotIO {
+ private final TalonFX pivotMotor;
+ // in rotations!!
+ private final StatusSignal position;
+ // in rotations!!
+ double zeroPosition;
+ Rotation2d targetPosition;
+ TalonFXConfiguration config;
+
+ public PivotIOReal() {
+ pivotMotor = new TalonFX(PivotConstants.pivotCANId);
+
+ config = new TalonFXConfiguration();
+
+ config.CurrentLimits.SupplyCurrentLimit = 30;
+ config.CurrentLimits.SupplyCurrentLimitEnable = true;
+ config.MotorOutput.NeutralMode = NeutralModeValue.Brake;
+ config.Slot0 =
+ new Slot0Configs()
+ .withKP(PivotConstants.p)
+ .withKI(PivotConstants.i)
+ .withKD(PivotConstants.d);
+
+ pivotMotor.getConfigurator().apply(config);
+
+ // in rotations!!
+ position = pivotMotor.getPosition();
+
+ BaseStatusSignal.setUpdateFrequencyForAll(20.0, position);
+ pivotMotor.optimizeBusUtilization(1.0);
+
+ // PivotConstants.pivotStart
+ zeroPosition = position.getValueAsDouble();
+ targetPosition = angleFromEncoder(zeroPosition);
+ }
+
+ public void updateInputs(PivotIOInputs inputs) {
+ BaseStatusSignal.refreshAll(position);
+ double currentPosition = position.getValueAsDouble();
+
+ inputs.pivotCurentAngle = angleFromEncoder(currentPosition);
+ inputs.pivotTargetAngle = targetPosition;
+ }
+
+ /** sets the target position where 0 is facing towards the back of the robot */
+ public void setTargetPosition(Rotation2d target) {
+ targetPosition = target;
+ pivotMotor.setPosition(encoderFromAngle(target));
+ }
+
+ private Rotation2d angleFromEncoder(double encoderTicks) {
+ // 2048 ticks per rotation
+ var delta =
+ Rotation2d.fromRotations((encoderTicks - zeroPosition) / PivotConstants.pivotGearRatio);
+
+ return delta.plus(PivotConstants.pivotStart);
+ }
+
+ private double encoderFromAngle(Rotation2d angle) {
+ var delta =
+ angle.minus(PivotConstants.pivotStart).getRotations() * PivotConstants.pivotGearRatio;
+
+ return delta + zeroPosition;
+ }
+}
diff --git a/src/main/java/frc/robot/subsystems/pivot/PivotIOSim.java b/src/main/java/frc/robot/subsystems/pivot/PivotIOSim.java
index 2c7702c..d8543be 100644
--- a/src/main/java/frc/robot/subsystems/pivot/PivotIOSim.java
+++ b/src/main/java/frc/robot/subsystems/pivot/PivotIOSim.java
@@ -1,5 +1,5 @@
-package frc.robot.subsystems.pivot;
-
-public class PivotIOSim implements PivotIO {
- // todo
-}
+package frc.robot.subsystems.pivot;
+
+public class PivotIOSim implements PivotIO {
+ // todo
+}
diff --git a/src/main/java/frc/robot/subsystems/shooter/Shooter.java b/src/main/java/frc/robot/subsystems/shooter/Shooter.java
index 8cb987f..54d3d64 100644
--- a/src/main/java/frc/robot/subsystems/shooter/Shooter.java
+++ b/src/main/java/frc/robot/subsystems/shooter/Shooter.java
@@ -1,49 +1,49 @@
-package frc.robot.subsystems.shooter;
-
-import static frc.robot.Constants.ShooterConstants.*;
-
-import edu.wpi.first.wpilibj2.command.Command;
-import edu.wpi.first.wpilibj2.command.InstantCommand;
-import edu.wpi.first.wpilibj2.command.SubsystemBase;
-
-public class Shooter extends SubsystemBase {
- private final ShooterIO io;
-
- public Shooter(ShooterIO io) {
- this.io = io;
- }
-
- public void shootersOn() {
- io.setTopShooterPower(shootingPower);
- io.setBottomShooterPower(shootingPower);
- }
-
- public void shootersOff() {
- io.setTopShooterPower(0);
- io.setBottomShooterPower(0);
- }
-
- public void conveyorOn() {
- io.setConveyorPower(conveyorPower);
- }
-
- public void conveyorOff() {
- io.setConveyorPower(0);
- }
-
- public Command shootersOnCommand() {
- return new InstantCommand(this::shootersOn, this);
- }
-
- public Command shootersOffCommand() {
- return new InstantCommand(this::shootersOff, this);
- }
-
- public Command conveyorOnCommand() {
- return new InstantCommand(this::conveyorOn, this);
- }
-
- public Command conveyorOffCommand() {
- return new InstantCommand(this::conveyorOff, this);
- }
-}
+package frc.robot.subsystems.shooter;
+
+import static frc.robot.Constants.ShooterConstants.*;
+
+import edu.wpi.first.wpilibj2.command.Command;
+import edu.wpi.first.wpilibj2.command.InstantCommand;
+import edu.wpi.first.wpilibj2.command.SubsystemBase;
+
+public class Shooter extends SubsystemBase {
+ private final ShooterIO io;
+
+ public Shooter(ShooterIO io) {
+ this.io = io;
+ }
+
+ public void shootersOn() {
+ io.setTopShooterPower(shootingPower);
+ io.setBottomShooterPower(shootingPower);
+ }
+
+ public void shootersOff() {
+ io.setTopShooterPower(0);
+ io.setBottomShooterPower(0);
+ }
+
+ public void conveyorOn() {
+ io.setConveyorPower(conveyorPower);
+ }
+
+ public void conveyorOff() {
+ io.setConveyorPower(0);
+ }
+
+ public Command shootersOnCommand() {
+ return new InstantCommand(this::shootersOn, this);
+ }
+
+ public Command shootersOffCommand() {
+ return new InstantCommand(this::shootersOff, this);
+ }
+
+ public Command conveyorOnCommand() {
+ return new InstantCommand(this::conveyorOn, this);
+ }
+
+ public Command conveyorOffCommand() {
+ return new InstantCommand(this::conveyorOff, this);
+ }
+}
diff --git a/src/main/java/frc/robot/subsystems/shooter/ShooterIO.java b/src/main/java/frc/robot/subsystems/shooter/ShooterIO.java
index 2c73715..3bf81a2 100644
--- a/src/main/java/frc/robot/subsystems/shooter/ShooterIO.java
+++ b/src/main/java/frc/robot/subsystems/shooter/ShooterIO.java
@@ -1,16 +1,16 @@
-package frc.robot.subsystems.shooter;
-
-import org.littletonrobotics.junction.AutoLog;
-
-public interface ShooterIO {
- @AutoLog
- class ShooterIOInputs {}
-
- default void updateInputs(ShooterIOInputs inputs) {}
-
- default void setTopShooterPower(double power) {}
-
- default void setBottomShooterPower(double power) {}
-
- default void setConveyorPower(double power) {}
-}
+package frc.robot.subsystems.shooter;
+
+import org.littletonrobotics.junction.AutoLog;
+
+public interface ShooterIO {
+ @AutoLog
+ class ShooterIOInputs {}
+
+ default void updateInputs(ShooterIOInputs inputs) {}
+
+ default void setTopShooterPower(double power) {}
+
+ default void setBottomShooterPower(double power) {}
+
+ default void setConveyorPower(double power) {}
+}
diff --git a/src/main/java/frc/robot/subsystems/shooter/ShooterIOReal.java b/src/main/java/frc/robot/subsystems/shooter/ShooterIOReal.java
index b123495..62995d0 100644
--- a/src/main/java/frc/robot/subsystems/shooter/ShooterIOReal.java
+++ b/src/main/java/frc/robot/subsystems/shooter/ShooterIOReal.java
@@ -1,50 +1,50 @@
-package frc.robot.subsystems.shooter;
-
-import static frc.robot.Constants.ShooterConstants.*;
-
-import com.ctre.phoenix6.configs.TalonFXConfiguration;
-import com.ctre.phoenix6.hardware.TalonFX;
-import com.ctre.phoenix6.signals.NeutralModeValue;
-import com.revrobotics.CANSparkBase.IdleMode;
-import com.revrobotics.CANSparkLowLevel.MotorType;
-import com.revrobotics.CANSparkMax;
-
-public class ShooterIOReal implements ShooterIO {
- private TalonFX topShooter;
- private TalonFX bottomShooter;
- private CANSparkMax conveyor;
-
- public ShooterIOReal() {
- topShooter = new TalonFX(topShooterCANId);
- bottomShooter = new TalonFX(bottomShooterCANId);
- conveyor = new CANSparkMax(conveyorCANId, MotorType.kBrushless);
-
- var config = new TalonFXConfiguration();
-
- config.CurrentLimits.SupplyCurrentLimit = 25;
- config.CurrentLimits.SupplyCurrentLimitEnable = true;
- config.MotorOutput.NeutralMode = NeutralModeValue.Coast;
-
- topShooter.getConfigurator().apply(config);
-
- // todo: test
- // config.MotorOutput.Inverted = InvertedValue.CounterClockwise_Positive;
- bottomShooter.getConfigurator().apply(config);
-
- conveyor.restoreFactoryDefaults();
- conveyor.setIdleMode(IdleMode.kBrake);
- conveyor.setSmartCurrentLimit(20);
- }
-
- public void setTopShooterPower(double power) {
- topShooter.set(power);
- }
-
- public void setBottomShooterPower(double power) {
- bottomShooter.set(power);
- }
-
- public void setConveyorPower(double power) {
- conveyor.set(power);
- }
-}
+package frc.robot.subsystems.shooter;
+
+import static frc.robot.Constants.ShooterConstants.*;
+
+import com.ctre.phoenix6.configs.TalonFXConfiguration;
+import com.ctre.phoenix6.hardware.TalonFX;
+import com.ctre.phoenix6.signals.NeutralModeValue;
+import com.revrobotics.CANSparkBase.IdleMode;
+import com.revrobotics.CANSparkLowLevel.MotorType;
+import com.revrobotics.CANSparkMax;
+
+public class ShooterIOReal implements ShooterIO {
+ private TalonFX topShooter;
+ private TalonFX bottomShooter;
+ private CANSparkMax conveyor;
+
+ public ShooterIOReal() {
+ topShooter = new TalonFX(topShooterCANId);
+ bottomShooter = new TalonFX(bottomShooterCANId);
+ conveyor = new CANSparkMax(conveyorCANId, MotorType.kBrushless);
+
+ var config = new TalonFXConfiguration();
+
+ config.CurrentLimits.SupplyCurrentLimit = 25;
+ config.CurrentLimits.SupplyCurrentLimitEnable = true;
+ config.MotorOutput.NeutralMode = NeutralModeValue.Coast;
+
+ topShooter.getConfigurator().apply(config);
+
+ // todo: test
+ // config.MotorOutput.Inverted = InvertedValue.CounterClockwise_Positive;
+ bottomShooter.getConfigurator().apply(config);
+
+ conveyor.restoreFactoryDefaults();
+ conveyor.setIdleMode(IdleMode.kBrake);
+ conveyor.setSmartCurrentLimit(20);
+ }
+
+ public void setTopShooterPower(double power) {
+ topShooter.set(power);
+ }
+
+ public void setBottomShooterPower(double power) {
+ bottomShooter.set(power);
+ }
+
+ public void setConveyorPower(double power) {
+ conveyor.set(power);
+ }
+}
diff --git a/src/main/java/frc/robot/subsystems/shooter/ShooterIOSim.java b/src/main/java/frc/robot/subsystems/shooter/ShooterIOSim.java
index 881cda0..8147c65 100644
--- a/src/main/java/frc/robot/subsystems/shooter/ShooterIOSim.java
+++ b/src/main/java/frc/robot/subsystems/shooter/ShooterIOSim.java
@@ -1,5 +1,5 @@
-package frc.robot.subsystems.shooter;
-
-public class ShooterIOSim implements ShooterIO {
- // todo
-}
+package frc.robot.subsystems.shooter;
+
+public class ShooterIOSim implements ShooterIO {
+ // todo
+}
diff --git a/src/main/java/frc/robot/util/LocalADStarAK.java b/src/main/java/frc/robot/util/LocalADStarAK.java
index 37222f2..30e126f 100644
--- a/src/main/java/frc/robot/util/LocalADStarAK.java
+++ b/src/main/java/frc/robot/util/LocalADStarAK.java
@@ -1,151 +1,151 @@
-package frc.robot.util;
-
-import com.pathplanner.lib.path.GoalEndState;
-import com.pathplanner.lib.path.PathConstraints;
-import com.pathplanner.lib.path.PathPlannerPath;
-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 java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import org.littletonrobotics.junction.LogTable;
-import org.littletonrobotics.junction.Logger;
-import org.littletonrobotics.junction.inputs.LoggableInputs;
-
-// NOTE: This file is available at
-// https://gist.github.com/mjansen4857/a8024b55eb427184dbd10ae8923bd57d
-
-public class LocalADStarAK implements Pathfinder {
- private final ADStarIO io = new ADStarIO();
-
- /**
- * Get if a new path has been calculated since the last time a path was retrieved
- *
- * @return True if a new path is available
- */
- @Override
- public boolean isNewPathAvailable() {
- if (Logger.hasReplaySource()) {
- io.updateIsNewPathAvailable();
- }
-
- Logger.processInputs("LocalADStarAK", io);
-
- return io.isNewPathAvailable;
- }
-
- /**
- * Get the most recently calculated path
- *
- * @param constraints The path constraints to use when creating the path
- * @param goalEndState The goal end state to use when creating the path
- * @return The PathPlannerPath created from the points calculated by the pathfinder
- */
- @Override
- public PathPlannerPath getCurrentPath(PathConstraints constraints, GoalEndState goalEndState) {
- if (Logger.hasReplaySource()) {
- io.updateCurrentPathPoints(constraints, goalEndState);
- }
-
- Logger.processInputs("LocalADStarAK", io);
-
- if (io.currentPathPoints.isEmpty()) {
- return null;
- }
-
- return PathPlannerPath.fromPathPoints(io.currentPathPoints, constraints, goalEndState);
- }
-
- /**
- * Set the start position to pathfind from
- *
- * @param startPosition Start position on the field. If this is within an obstacle it will be
- * moved to the nearest non-obstacle node.
- */
- @Override
- public void setStartPosition(Translation2d startPosition) {
- if (Logger.hasReplaySource()) {
- io.adStar.setStartPosition(startPosition);
- }
- }
-
- /**
- * Set the goal position to pathfind to
- *
- * @param goalPosition Goal position on the field. f this is within an obstacle it will be moved
- * to the nearest non-obstacle node.
- */
- @Override
- public void setGoalPosition(Translation2d goalPosition) {
- if (Logger.hasReplaySource()) {
- io.adStar.setGoalPosition(goalPosition);
- }
- }
-
- /**
- * Set the dynamic obstacles that should be avoided while pathfinding.
- *
- * @param obs A List of Translation2d pairs representing obstacles. Each Translation2d represents
- * opposite corners of a bounding box.
- * @param currentRobotPos The current position of the robot. This is needed to change the start
- * position of the path to properly avoid obstacles
- */
- @Override
- public void setDynamicObstacles(
- List> obs, Translation2d currentRobotPos) {
- io.adStar.setDynamicObstacles(obs, currentRobotPos);
- }
-
- private static class ADStarIO implements LoggableInputs {
- public LocalADStar adStar = new LocalADStar();
- public boolean isNewPathAvailable = false;
- public List currentPathPoints = Collections.emptyList();
-
- @Override
- public void toLog(LogTable table) {
- table.put("IsNewPathAvailable", isNewPathAvailable);
-
- double[] pointsLogged = new double[currentPathPoints.size() * 2];
- int idx = 0;
- for (PathPoint point : currentPathPoints) {
- pointsLogged[idx] = point.position.getX();
- pointsLogged[idx + 1] = point.position.getY();
- idx += 2;
- }
-
- table.put("CurrentPathPoints", pointsLogged);
- }
-
- @Override
- public void fromLog(LogTable table) {
- isNewPathAvailable = table.get("IsNewPathAvailable", false);
-
- double[] pointsLogged = table.get("CurrentPathPoints", new double[0]);
-
- List pathPoints = new ArrayList<>();
- for (int i = 0; i < pointsLogged.length; i += 2) {
- pathPoints.add(
- new PathPoint(new Translation2d(pointsLogged[i], pointsLogged[i + 1]), null));
- }
-
- currentPathPoints = pathPoints;
- }
-
- public void updateIsNewPathAvailable() {
- isNewPathAvailable = adStar.isNewPathAvailable();
- }
-
- public void updateCurrentPathPoints(PathConstraints constraints, GoalEndState goalEndState) {
- PathPlannerPath currentPath = adStar.getCurrentPath(constraints, goalEndState);
-
- if (currentPath != null) {
- currentPathPoints = currentPath.getAllPathPoints();
- } else {
- currentPathPoints = Collections.emptyList();
- }
- }
- }
-}
+package frc.robot.util;
+
+import com.pathplanner.lib.path.GoalEndState;
+import com.pathplanner.lib.path.PathConstraints;
+import com.pathplanner.lib.path.PathPlannerPath;
+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 java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.littletonrobotics.junction.LogTable;
+import org.littletonrobotics.junction.Logger;
+import org.littletonrobotics.junction.inputs.LoggableInputs;
+
+// NOTE: This file is available at
+// https://gist.github.com/mjansen4857/a8024b55eb427184dbd10ae8923bd57d
+
+public class LocalADStarAK implements Pathfinder {
+ private final ADStarIO io = new ADStarIO();
+
+ /**
+ * Get if a new path has been calculated since the last time a path was retrieved
+ *
+ * @return True if a new path is available
+ */
+ @Override
+ public boolean isNewPathAvailable() {
+ if (Logger.hasReplaySource()) {
+ io.updateIsNewPathAvailable();
+ }
+
+ Logger.processInputs("LocalADStarAK", io);
+
+ return io.isNewPathAvailable;
+ }
+
+ /**
+ * Get the most recently calculated path
+ *
+ * @param constraints The path constraints to use when creating the path
+ * @param goalEndState The goal end state to use when creating the path
+ * @return The PathPlannerPath created from the points calculated by the pathfinder
+ */
+ @Override
+ public PathPlannerPath getCurrentPath(PathConstraints constraints, GoalEndState goalEndState) {
+ if (Logger.hasReplaySource()) {
+ io.updateCurrentPathPoints(constraints, goalEndState);
+ }
+
+ Logger.processInputs("LocalADStarAK", io);
+
+ if (io.currentPathPoints.isEmpty()) {
+ return null;
+ }
+
+ return PathPlannerPath.fromPathPoints(io.currentPathPoints, constraints, goalEndState);
+ }
+
+ /**
+ * Set the start position to pathfind from
+ *
+ * @param startPosition Start position on the field. If this is within an obstacle it will be
+ * moved to the nearest non-obstacle node.
+ */
+ @Override
+ public void setStartPosition(Translation2d startPosition) {
+ if (Logger.hasReplaySource()) {
+ io.adStar.setStartPosition(startPosition);
+ }
+ }
+
+ /**
+ * Set the goal position to pathfind to
+ *
+ * @param goalPosition Goal position on the field. f this is within an obstacle it will be moved
+ * to the nearest non-obstacle node.
+ */
+ @Override
+ public void setGoalPosition(Translation2d goalPosition) {
+ if (Logger.hasReplaySource()) {
+ io.adStar.setGoalPosition(goalPosition);
+ }
+ }
+
+ /**
+ * Set the dynamic obstacles that should be avoided while pathfinding.
+ *
+ * @param obs A List of Translation2d pairs representing obstacles. Each Translation2d represents
+ * opposite corners of a bounding box.
+ * @param currentRobotPos The current position of the robot. This is needed to change the start
+ * position of the path to properly avoid obstacles
+ */
+ @Override
+ public void setDynamicObstacles(
+ List> obs, Translation2d currentRobotPos) {
+ io.adStar.setDynamicObstacles(obs, currentRobotPos);
+ }
+
+ private static class ADStarIO implements LoggableInputs {
+ public LocalADStar adStar = new LocalADStar();
+ public boolean isNewPathAvailable = false;
+ public List currentPathPoints = Collections.emptyList();
+
+ @Override
+ public void toLog(LogTable table) {
+ table.put("IsNewPathAvailable", isNewPathAvailable);
+
+ double[] pointsLogged = new double[currentPathPoints.size() * 2];
+ int idx = 0;
+ for (PathPoint point : currentPathPoints) {
+ pointsLogged[idx] = point.position.getX();
+ pointsLogged[idx + 1] = point.position.getY();
+ idx += 2;
+ }
+
+ table.put("CurrentPathPoints", pointsLogged);
+ }
+
+ @Override
+ public void fromLog(LogTable table) {
+ isNewPathAvailable = table.get("IsNewPathAvailable", false);
+
+ double[] pointsLogged = table.get("CurrentPathPoints", new double[0]);
+
+ List pathPoints = new ArrayList<>();
+ for (int i = 0; i < pointsLogged.length; i += 2) {
+ pathPoints.add(
+ new PathPoint(new Translation2d(pointsLogged[i], pointsLogged[i + 1]), null));
+ }
+
+ currentPathPoints = pathPoints;
+ }
+
+ public void updateIsNewPathAvailable() {
+ isNewPathAvailable = adStar.isNewPathAvailable();
+ }
+
+ public void updateCurrentPathPoints(PathConstraints constraints, GoalEndState goalEndState) {
+ PathPlannerPath currentPath = adStar.getCurrentPath(constraints, goalEndState);
+
+ if (currentPath != null) {
+ currentPathPoints = currentPath.getAllPathPoints();
+ } else {
+ currentPathPoints = Collections.emptyList();
+ }
+ }
+ }
+}
diff --git a/src/main/java/frc/robot/util/PolynomialRegression.java b/src/main/java/frc/robot/util/PolynomialRegression.java
index 28c5796..658d332 100644
--- a/src/main/java/frc/robot/util/PolynomialRegression.java
+++ b/src/main/java/frc/robot/util/PolynomialRegression.java
@@ -1,205 +1,205 @@
-package frc.robot.util;
-
-import Jama.Matrix;
-import Jama.QRDecomposition;
-
-// NOTE: This file is available at
-// http://algs4.cs.princeton.edu/14analysis/PolynomialRegression.java.html
-
-/**
- * The {@code PolynomialRegression} class performs a polynomial regression on an set of N
- * data points (yi, xi). That is, it fits a polynomial
- * y = β0 + β1 x + β2
- * x2 + ... + βd xd (where
- * y is the response variable, x is the predictor variable, and the
- * βi are the regression coefficients) that minimizes the sum of squared
- * residuals of the multiple regression model. It also computes associated the coefficient of
- * determination R2.
- *
- * This implementation performs a QR-decomposition of the underlying Vandermonde matrix, so it is
- * neither the fastest nor the most numerically stable way to perform the polynomial regression.
- *
- * @author Robert Sedgewick
- * @author Kevin Wayne
- */
-public class PolynomialRegression implements Comparable {
- private final String variableName; // name of the predictor variable
- private int degree; // degree of the polynomial regression
- private Matrix beta; // the polynomial regression coefficients
- private double sse; // sum of squares due to error
- private double sst; // total sum of squares
-
- /**
- * Performs a polynomial reggression on the data points {@code (y[i], x[i])}. Uses n as the name
- * of the predictor variable.
- *
- * @param x the values of the predictor variable
- * @param y the corresponding values of the response variable
- * @param degree the degree of the polynomial to fit
- * @throws IllegalArgumentException if the lengths of the two arrays are not equal
- */
- public PolynomialRegression(double[] x, double[] y, int degree) {
- this(x, y, degree, "n");
- }
-
- /**
- * Performs a polynomial reggression on the data points {@code (y[i], x[i])}.
- *
- * @param x the values of the predictor variable
- * @param y the corresponding values of the response variable
- * @param degree the degree of the polynomial to fit
- * @param variableName the name of the predictor variable
- * @throws IllegalArgumentException if the lengths of the two arrays are not equal
- */
- public PolynomialRegression(double[] x, double[] y, int degree, String variableName) {
- this.degree = degree;
- this.variableName = variableName;
-
- int n = x.length;
- QRDecomposition qr = null;
- Matrix matrixX = null;
-
- // in case Vandermonde matrix does not have full rank, reduce degree until it
- // does
- while (true) {
-
- // build Vandermonde matrix
- double[][] vandermonde = new double[n][this.degree + 1];
- for (int i = 0; i < n; i++) {
- for (int j = 0; j <= this.degree; j++) {
- vandermonde[i][j] = Math.pow(x[i], j);
- }
- }
- matrixX = new Matrix(vandermonde);
-
- // find least squares solution
- qr = new QRDecomposition(matrixX);
- if (qr.isFullRank()) break;
-
- // decrease degree and try again
- this.degree--;
- }
-
- // create matrix from vector
- Matrix matrixY = new Matrix(y, n);
-
- // linear regression coefficients
- beta = qr.solve(matrixY);
-
- // mean of y[] values
- double sum = 0.0;
- for (int i = 0; i < n; i++) sum += y[i];
- double mean = sum / n;
-
- // total variation to be accounted for
- for (int i = 0; i < n; i++) {
- double dev = y[i] - mean;
- sst += dev * dev;
- }
-
- // variation not accounted for
- Matrix residuals = matrixX.times(beta).minus(matrixY);
- sse = residuals.norm2() * residuals.norm2();
- }
-
- /**
- * Returns the {@code j}th regression coefficient.
- *
- * @param j the index
- * @return the {@code j}th regression coefficient
- */
- public double beta(int j) {
- // to make -0.0 print as 0.0
- if (Math.abs(beta.get(j, 0)) < 1E-4) return 0.0;
- return beta.get(j, 0);
- }
-
- /**
- * Returns the degree of the polynomial to fit.
- *
- * @return the degree of the polynomial to fit
- */
- public int degree() {
- return degree;
- }
-
- /**
- * Returns the coefficient of determination R2.
- *
- * @return the coefficient of determination R2, which is a real number between
- * 0 and 1
- */
- public double R2() {
- if (sst == 0.0) return 1.0; // constant function
- return 1.0 - sse / sst;
- }
-
- /**
- * Returns the expected response {@code y} given the value of the predictor variable {@code x}.
- *
- * @param x the value of the predictor variable
- * @return the expected response {@code y} given the value of the predictor variable {@code x}
- */
- public double predict(double x) {
- // horner's method
- double y = 0.0;
- for (int j = degree; j >= 0; j--) y = beta(j) + (x * y);
- return y;
- }
-
- /**
- * Returns a string representation of the polynomial regression model.
- *
- * @return a string representation of the polynomial regression model, including the best-fit
- * polynomial and the coefficient of determination R2
- */
- public String toString() {
- StringBuilder s = new StringBuilder();
- int j = degree;
-
- // ignoring leading zero coefficients
- while (j >= 0 && Math.abs(beta(j)) < 1E-5) j--;
-
- // create remaining terms
- while (j >= 0) {
- if (j == 0) s.append(String.format("%.10f ", beta(j)));
- else if (j == 1) s.append(String.format("%.10f %s + ", beta(j), variableName));
- else s.append(String.format("%.10f %s^%d + ", beta(j), variableName, j));
- j--;
- }
- s = s.append(" (R^2 = " + String.format("%.3f", R2()) + ")");
-
- // replace "+ -2n" with "- 2n"
- return s.toString().replace("+ -", "- ");
- }
-
- /** Compare lexicographically. */
- public int compareTo(PolynomialRegression that) {
- double EPSILON = 1E-5;
- int maxDegree = Math.max(this.degree(), that.degree());
- for (int j = maxDegree; j >= 0; j--) {
- double term1 = 0.0;
- double term2 = 0.0;
- if (this.degree() >= j) term1 = this.beta(j);
- if (that.degree() >= j) term2 = that.beta(j);
- if (Math.abs(term1) < EPSILON) term1 = 0.0;
- if (Math.abs(term2) < EPSILON) term2 = 0.0;
- if (term1 < term2) return -1;
- else if (term1 > term2) return +1;
- }
- return 0;
- }
-
- /**
- * Unit tests the {@code PolynomialRegression} data type.
- *
- * @param args the command-line arguments
- */
- public static void main(String[] args) {
- double[] x = {10, 20, 40, 80, 160, 200};
- double[] y = {100, 350, 1500, 6700, 20160, 40000};
- PolynomialRegression regression = new PolynomialRegression(x, y, 3);
-
- System.out.println(regression);
- }
-}
+package frc.robot.util;
+
+import Jama.Matrix;
+import Jama.QRDecomposition;
+
+// NOTE: This file is available at
+// http://algs4.cs.princeton.edu/14analysis/PolynomialRegression.java.html
+
+/**
+ * The {@code PolynomialRegression} class performs a polynomial regression on an set of N
+ * data points (yi, xi). That is, it fits a polynomial
+ * y = β0 + β1 x + β2
+ * x2 + ... + βd xd (where
+ * y is the response variable, x is the predictor variable, and the
+ * βi are the regression coefficients) that minimizes the sum of squared
+ * residuals of the multiple regression model. It also computes associated the coefficient of
+ * determination R2.
+ *
+ * This implementation performs a QR-decomposition of the underlying Vandermonde matrix, so it is
+ * neither the fastest nor the most numerically stable way to perform the polynomial regression.
+ *
+ * @author Robert Sedgewick
+ * @author Kevin Wayne
+ */
+public class PolynomialRegression implements Comparable {
+ private final String variableName; // name of the predictor variable
+ private int degree; // degree of the polynomial regression
+ private Matrix beta; // the polynomial regression coefficients
+ private double sse; // sum of squares due to error
+ private double sst; // total sum of squares
+
+ /**
+ * Performs a polynomial reggression on the data points {@code (y[i], x[i])}. Uses n as the name
+ * of the predictor variable.
+ *
+ * @param x the values of the predictor variable
+ * @param y the corresponding values of the response variable
+ * @param degree the degree of the polynomial to fit
+ * @throws IllegalArgumentException if the lengths of the two arrays are not equal
+ */
+ public PolynomialRegression(double[] x, double[] y, int degree) {
+ this(x, y, degree, "n");
+ }
+
+ /**
+ * Performs a polynomial reggression on the data points {@code (y[i], x[i])}.
+ *
+ * @param x the values of the predictor variable
+ * @param y the corresponding values of the response variable
+ * @param degree the degree of the polynomial to fit
+ * @param variableName the name of the predictor variable
+ * @throws IllegalArgumentException if the lengths of the two arrays are not equal
+ */
+ public PolynomialRegression(double[] x, double[] y, int degree, String variableName) {
+ this.degree = degree;
+ this.variableName = variableName;
+
+ int n = x.length;
+ QRDecomposition qr = null;
+ Matrix matrixX = null;
+
+ // in case Vandermonde matrix does not have full rank, reduce degree until it
+ // does
+ while (true) {
+
+ // build Vandermonde matrix
+ double[][] vandermonde = new double[n][this.degree + 1];
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j <= this.degree; j++) {
+ vandermonde[i][j] = Math.pow(x[i], j);
+ }
+ }
+ matrixX = new Matrix(vandermonde);
+
+ // find least squares solution
+ qr = new QRDecomposition(matrixX);
+ if (qr.isFullRank()) break;
+
+ // decrease degree and try again
+ this.degree--;
+ }
+
+ // create matrix from vector
+ Matrix matrixY = new Matrix(y, n);
+
+ // linear regression coefficients
+ beta = qr.solve(matrixY);
+
+ // mean of y[] values
+ double sum = 0.0;
+ for (int i = 0; i < n; i++) sum += y[i];
+ double mean = sum / n;
+
+ // total variation to be accounted for
+ for (int i = 0; i < n; i++) {
+ double dev = y[i] - mean;
+ sst += dev * dev;
+ }
+
+ // variation not accounted for
+ Matrix residuals = matrixX.times(beta).minus(matrixY);
+ sse = residuals.norm2() * residuals.norm2();
+ }
+
+ /**
+ * Returns the {@code j}th regression coefficient.
+ *
+ * @param j the index
+ * @return the {@code j}th regression coefficient
+ */
+ public double beta(int j) {
+ // to make -0.0 print as 0.0
+ if (Math.abs(beta.get(j, 0)) < 1E-4) return 0.0;
+ return beta.get(j, 0);
+ }
+
+ /**
+ * Returns the degree of the polynomial to fit.
+ *
+ * @return the degree of the polynomial to fit
+ */
+ public int degree() {
+ return degree;
+ }
+
+ /**
+ * Returns the coefficient of determination R2.
+ *
+ * @return the coefficient of determination R2, which is a real number between
+ * 0 and 1
+ */
+ public double R2() {
+ if (sst == 0.0) return 1.0; // constant function
+ return 1.0 - sse / sst;
+ }
+
+ /**
+ * Returns the expected response {@code y} given the value of the predictor variable {@code x}.
+ *
+ * @param x the value of the predictor variable
+ * @return the expected response {@code y} given the value of the predictor variable {@code x}
+ */
+ public double predict(double x) {
+ // horner's method
+ double y = 0.0;
+ for (int j = degree; j >= 0; j--) y = beta(j) + (x * y);
+ return y;
+ }
+
+ /**
+ * Returns a string representation of the polynomial regression model.
+ *
+ * @return a string representation of the polynomial regression model, including the best-fit
+ * polynomial and the coefficient of determination R2
+ */
+ public String toString() {
+ StringBuilder s = new StringBuilder();
+ int j = degree;
+
+ // ignoring leading zero coefficients
+ while (j >= 0 && Math.abs(beta(j)) < 1E-5) j--;
+
+ // create remaining terms
+ while (j >= 0) {
+ if (j == 0) s.append(String.format("%.10f ", beta(j)));
+ else if (j == 1) s.append(String.format("%.10f %s + ", beta(j), variableName));
+ else s.append(String.format("%.10f %s^%d + ", beta(j), variableName, j));
+ j--;
+ }
+ s = s.append(" (R^2 = " + String.format("%.3f", R2()) + ")");
+
+ // replace "+ -2n" with "- 2n"
+ return s.toString().replace("+ -", "- ");
+ }
+
+ /** Compare lexicographically. */
+ public int compareTo(PolynomialRegression that) {
+ double EPSILON = 1E-5;
+ int maxDegree = Math.max(this.degree(), that.degree());
+ for (int j = maxDegree; j >= 0; j--) {
+ double term1 = 0.0;
+ double term2 = 0.0;
+ if (this.degree() >= j) term1 = this.beta(j);
+ if (that.degree() >= j) term2 = that.beta(j);
+ if (Math.abs(term1) < EPSILON) term1 = 0.0;
+ if (Math.abs(term2) < EPSILON) term2 = 0.0;
+ if (term1 < term2) return -1;
+ else if (term1 > term2) return +1;
+ }
+ return 0;
+ }
+
+ /**
+ * Unit tests the {@code PolynomialRegression} data type.
+ *
+ * @param args the command-line arguments
+ */
+ public static void main(String[] args) {
+ double[] x = {10, 20, 40, 80, 160, 200};
+ double[] y = {100, 350, 1500, 6700, 20160, 40000};
+ PolynomialRegression regression = new PolynomialRegression(x, y, 3);
+
+ System.out.println(regression);
+ }
+}
diff --git a/vendordeps/AdvantageKit.json b/vendordeps/AdvantageKit.json
index a3a16b6..a9dc4bc 100644
--- a/vendordeps/AdvantageKit.json
+++ b/vendordeps/AdvantageKit.json
@@ -1,42 +1,42 @@
-{
- "fileName": "AdvantageKit.json",
- "name": "AdvantageKit",
- "version": "3.0.0",
- "uuid": "d820cc26-74e3-11ec-90d6-0242ac120003",
- "frcYear": "2024",
- "mavenUrls": [],
- "jsonUrl": "https://github.com/Mechanical-Advantage/AdvantageKit/releases/latest/download/AdvantageKit.json",
- "javaDependencies": [
- {
- "groupId": "org.littletonrobotics.akit.junction",
- "artifactId": "wpilib-shim",
- "version": "3.0.0"
- },
- {
- "groupId": "org.littletonrobotics.akit.junction",
- "artifactId": "junction-core",
- "version": "3.0.0"
- },
- {
- "groupId": "org.littletonrobotics.akit.conduit",
- "artifactId": "conduit-api",
- "version": "3.0.0"
- }
- ],
- "jniDependencies": [
- {
- "groupId": "org.littletonrobotics.akit.conduit",
- "artifactId": "conduit-wpilibio",
- "version": "3.0.0",
- "skipInvalidPlatforms": false,
- "isJar": false,
- "validPlatforms": [
- "linuxathena",
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ]
- }
- ],
- "cppDependencies": []
-}
+{
+ "fileName": "AdvantageKit.json",
+ "name": "AdvantageKit",
+ "version": "3.1.0",
+ "uuid": "d820cc26-74e3-11ec-90d6-0242ac120003",
+ "frcYear": "2024",
+ "mavenUrls": [],
+ "jsonUrl": "https://github.com/Mechanical-Advantage/AdvantageKit/releases/latest/download/AdvantageKit.json",
+ "javaDependencies": [
+ {
+ "groupId": "org.littletonrobotics.akit.junction",
+ "artifactId": "wpilib-shim",
+ "version": "3.1.0"
+ },
+ {
+ "groupId": "org.littletonrobotics.akit.junction",
+ "artifactId": "junction-core",
+ "version": "3.1.0"
+ },
+ {
+ "groupId": "org.littletonrobotics.akit.conduit",
+ "artifactId": "conduit-api",
+ "version": "3.1.0"
+ }
+ ],
+ "jniDependencies": [
+ {
+ "groupId": "org.littletonrobotics.akit.conduit",
+ "artifactId": "conduit-wpilibio",
+ "version": "3.1.0",
+ "skipInvalidPlatforms": false,
+ "isJar": false,
+ "validPlatforms": [
+ "linuxathena",
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ]
+ }
+ ],
+ "cppDependencies": []
+}
diff --git a/vendordeps/PathplannerLib.json b/vendordeps/PathplannerLib.json
index d8e3470..507c97d 100644
--- a/vendordeps/PathplannerLib.json
+++ b/vendordeps/PathplannerLib.json
@@ -1,38 +1,38 @@
-{
- "fileName": "PathplannerLib.json",
- "name": "PathplannerLib",
- "version": "2024.1.2",
- "uuid": "1b42324f-17c6-4875-8e77-1c312bc8c786",
- "frcYear": "2024",
- "mavenUrls": [
- "https://3015rangerrobotics.github.io/pathplannerlib/repo"
- ],
- "jsonUrl": "https://3015rangerrobotics.github.io/pathplannerlib/PathplannerLib.json",
- "javaDependencies": [
- {
- "groupId": "com.pathplanner.lib",
- "artifactId": "PathplannerLib-java",
- "version": "2024.1.2"
- }
- ],
- "jniDependencies": [],
- "cppDependencies": [
- {
- "groupId": "com.pathplanner.lib",
- "artifactId": "PathplannerLib-cpp",
- "version": "2024.1.2",
- "libName": "PathplannerLib",
- "headerClassifier": "headers",
- "sharedLibrary": false,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal",
- "linuxathena",
- "linuxarm32",
- "linuxarm64"
- ]
- }
- ]
-}
+{
+ "fileName": "PathplannerLib.json",
+ "name": "PathplannerLib",
+ "version": "2024.1.2",
+ "uuid": "1b42324f-17c6-4875-8e77-1c312bc8c786",
+ "frcYear": "2024",
+ "mavenUrls": [
+ "https://3015rangerrobotics.github.io/pathplannerlib/repo"
+ ],
+ "jsonUrl": "https://3015rangerrobotics.github.io/pathplannerlib/PathplannerLib.json",
+ "javaDependencies": [
+ {
+ "groupId": "com.pathplanner.lib",
+ "artifactId": "PathplannerLib-java",
+ "version": "2024.1.2"
+ }
+ ],
+ "jniDependencies": [],
+ "cppDependencies": [
+ {
+ "groupId": "com.pathplanner.lib",
+ "artifactId": "PathplannerLib-cpp",
+ "version": "2024.1.2",
+ "libName": "PathplannerLib",
+ "headerClassifier": "headers",
+ "sharedLibrary": false,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal",
+ "linuxathena",
+ "linuxarm32",
+ "linuxarm64"
+ ]
+ }
+ ]
+}
diff --git a/vendordeps/Phoenix5.json b/vendordeps/Phoenix5.json
index f572dcc..bdab4d3 100644
--- a/vendordeps/Phoenix5.json
+++ b/vendordeps/Phoenix5.json
@@ -1,151 +1,151 @@
-{
- "fileName": "Phoenix5.json",
- "name": "CTRE-Phoenix (v5)",
- "version": "5.33.0",
- "frcYear": 2024,
- "uuid": "ab676553-b602-441f-a38d-f1296eff6537",
- "mavenUrls": [
- "https://maven.ctr-electronics.com/release/"
- ],
- "jsonUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix/Phoenix5-frc2024-latest.json",
- "requires": [
- {
- "uuid": "e995de00-2c64-4df5-8831-c1441420ff19",
- "errorMessage": "Phoenix 5 requires low-level libraries from Phoenix 6. Please add the Phoenix 6 vendordep before adding Phoenix 5.",
- "offlineFileName": "Phoenix6.json",
- "onlineUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix6/latest/Phoenix6-frc2024-latest.json"
- }
- ],
- "javaDependencies": [
- {
- "groupId": "com.ctre.phoenix",
- "artifactId": "api-java",
- "version": "5.33.0"
- },
- {
- "groupId": "com.ctre.phoenix",
- "artifactId": "wpiapi-java",
- "version": "5.33.0"
- }
- ],
- "jniDependencies": [
- {
- "groupId": "com.ctre.phoenix",
- "artifactId": "cci",
- "version": "5.33.0",
- "isJar": false,
- "skipInvalidPlatforms": true,
- "validPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "linuxathena"
- ],
- "simMode": "hwsim"
- },
- {
- "groupId": "com.ctre.phoenix.sim",
- "artifactId": "cci-sim",
- "version": "5.33.0",
- "isJar": false,
- "skipInvalidPlatforms": true,
- "validPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- }
- ],
- "cppDependencies": [
- {
- "groupId": "com.ctre.phoenix",
- "artifactId": "wpiapi-cpp",
- "version": "5.33.0",
- "libName": "CTRE_Phoenix_WPI",
- "headerClassifier": "headers",
- "sharedLibrary": true,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "linuxathena"
- ],
- "simMode": "hwsim"
- },
- {
- "groupId": "com.ctre.phoenix",
- "artifactId": "api-cpp",
- "version": "5.33.0",
- "libName": "CTRE_Phoenix",
- "headerClassifier": "headers",
- "sharedLibrary": true,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "linuxathena"
- ],
- "simMode": "hwsim"
- },
- {
- "groupId": "com.ctre.phoenix",
- "artifactId": "cci",
- "version": "5.33.0",
- "libName": "CTRE_PhoenixCCI",
- "headerClassifier": "headers",
- "sharedLibrary": true,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "linuxathena"
- ],
- "simMode": "hwsim"
- },
- {
- "groupId": "com.ctre.phoenix.sim",
- "artifactId": "wpiapi-cpp-sim",
- "version": "5.33.0",
- "libName": "CTRE_Phoenix_WPISim",
- "headerClassifier": "headers",
- "sharedLibrary": true,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- },
- {
- "groupId": "com.ctre.phoenix.sim",
- "artifactId": "api-cpp-sim",
- "version": "5.33.0",
- "libName": "CTRE_PhoenixSim",
- "headerClassifier": "headers",
- "sharedLibrary": true,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- },
- {
- "groupId": "com.ctre.phoenix.sim",
- "artifactId": "cci-sim",
- "version": "5.33.0",
- "libName": "CTRE_PhoenixCCISim",
- "headerClassifier": "headers",
- "sharedLibrary": true,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- }
- ]
-}
+{
+ "fileName": "Phoenix5.json",
+ "name": "CTRE-Phoenix (v5)",
+ "version": "5.33.0",
+ "frcYear": 2024,
+ "uuid": "ab676553-b602-441f-a38d-f1296eff6537",
+ "mavenUrls": [
+ "https://maven.ctr-electronics.com/release/"
+ ],
+ "jsonUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix/Phoenix5-frc2024-latest.json",
+ "requires": [
+ {
+ "uuid": "e995de00-2c64-4df5-8831-c1441420ff19",
+ "errorMessage": "Phoenix 5 requires low-level libraries from Phoenix 6. Please add the Phoenix 6 vendordep before adding Phoenix 5.",
+ "offlineFileName": "Phoenix6.json",
+ "onlineUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix6/latest/Phoenix6-frc2024-latest.json"
+ }
+ ],
+ "javaDependencies": [
+ {
+ "groupId": "com.ctre.phoenix",
+ "artifactId": "api-java",
+ "version": "5.33.0"
+ },
+ {
+ "groupId": "com.ctre.phoenix",
+ "artifactId": "wpiapi-java",
+ "version": "5.33.0"
+ }
+ ],
+ "jniDependencies": [
+ {
+ "groupId": "com.ctre.phoenix",
+ "artifactId": "cci",
+ "version": "5.33.0",
+ "isJar": false,
+ "skipInvalidPlatforms": true,
+ "validPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "linuxathena"
+ ],
+ "simMode": "hwsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix.sim",
+ "artifactId": "cci-sim",
+ "version": "5.33.0",
+ "isJar": false,
+ "skipInvalidPlatforms": true,
+ "validPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ }
+ ],
+ "cppDependencies": [
+ {
+ "groupId": "com.ctre.phoenix",
+ "artifactId": "wpiapi-cpp",
+ "version": "5.33.0",
+ "libName": "CTRE_Phoenix_WPI",
+ "headerClassifier": "headers",
+ "sharedLibrary": true,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "linuxathena"
+ ],
+ "simMode": "hwsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix",
+ "artifactId": "api-cpp",
+ "version": "5.33.0",
+ "libName": "CTRE_Phoenix",
+ "headerClassifier": "headers",
+ "sharedLibrary": true,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "linuxathena"
+ ],
+ "simMode": "hwsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix",
+ "artifactId": "cci",
+ "version": "5.33.0",
+ "libName": "CTRE_PhoenixCCI",
+ "headerClassifier": "headers",
+ "sharedLibrary": true,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "linuxathena"
+ ],
+ "simMode": "hwsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix.sim",
+ "artifactId": "wpiapi-cpp-sim",
+ "version": "5.33.0",
+ "libName": "CTRE_Phoenix_WPISim",
+ "headerClassifier": "headers",
+ "sharedLibrary": true,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix.sim",
+ "artifactId": "api-cpp-sim",
+ "version": "5.33.0",
+ "libName": "CTRE_PhoenixSim",
+ "headerClassifier": "headers",
+ "sharedLibrary": true,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix.sim",
+ "artifactId": "cci-sim",
+ "version": "5.33.0",
+ "libName": "CTRE_PhoenixCCISim",
+ "headerClassifier": "headers",
+ "sharedLibrary": true,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ }
+ ]
+}
diff --git a/vendordeps/Phoenix6.json b/vendordeps/Phoenix6.json
index 42d1c3e..9575ac4 100644
--- a/vendordeps/Phoenix6.json
+++ b/vendordeps/Phoenix6.json
@@ -1,339 +1,339 @@
-{
- "fileName": "Phoenix6.json",
- "name": "CTRE-Phoenix (v6)",
- "version": "24.1.0",
- "frcYear": 2024,
- "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-frc2024-latest.json",
- "conflictsWith": [
- {
- "uuid": "3fcf3402-e646-4fa6-971e-18afe8173b1a",
- "errorMessage": "The combined Phoenix-6-And-5 vendordep is no longer supported. Please remove the vendordep and instead add both the latest Phoenix 6 vendordep and Phoenix 5 vendordep.",
- "offlineFileName": "Phoenix6And5.json"
- }
- ],
- "javaDependencies": [
- {
- "groupId": "com.ctre.phoenix6",
- "artifactId": "wpiapi-java",
- "version": "24.1.0"
- }
- ],
- "jniDependencies": [
- {
- "groupId": "com.ctre.phoenix6",
- "artifactId": "tools",
- "version": "24.1.0",
- "isJar": false,
- "skipInvalidPlatforms": true,
- "validPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "linuxathena"
- ],
- "simMode": "hwsim"
- },
- {
- "groupId": "com.ctre.phoenix6.sim",
- "artifactId": "tools-sim",
- "version": "24.1.0",
- "isJar": false,
- "skipInvalidPlatforms": true,
- "validPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- },
- {
- "groupId": "com.ctre.phoenix6.sim",
- "artifactId": "simTalonSRX",
- "version": "24.1.0",
- "isJar": false,
- "skipInvalidPlatforms": true,
- "validPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- },
- {
- "groupId": "com.ctre.phoenix6.sim",
- "artifactId": "simTalonFX",
- "version": "24.1.0",
- "isJar": false,
- "skipInvalidPlatforms": true,
- "validPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- },
- {
- "groupId": "com.ctre.phoenix6.sim",
- "artifactId": "simVictorSPX",
- "version": "24.1.0",
- "isJar": false,
- "skipInvalidPlatforms": true,
- "validPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- },
- {
- "groupId": "com.ctre.phoenix6.sim",
- "artifactId": "simPigeonIMU",
- "version": "24.1.0",
- "isJar": false,
- "skipInvalidPlatforms": true,
- "validPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- },
- {
- "groupId": "com.ctre.phoenix6.sim",
- "artifactId": "simCANCoder",
- "version": "24.1.0",
- "isJar": false,
- "skipInvalidPlatforms": true,
- "validPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- },
- {
- "groupId": "com.ctre.phoenix6.sim",
- "artifactId": "simProTalonFX",
- "version": "24.1.0",
- "isJar": false,
- "skipInvalidPlatforms": true,
- "validPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- },
- {
- "groupId": "com.ctre.phoenix6.sim",
- "artifactId": "simProCANcoder",
- "version": "24.1.0",
- "isJar": false,
- "skipInvalidPlatforms": true,
- "validPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- },
- {
- "groupId": "com.ctre.phoenix6.sim",
- "artifactId": "simProPigeon2",
- "version": "24.1.0",
- "isJar": false,
- "skipInvalidPlatforms": true,
- "validPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- }
- ],
- "cppDependencies": [
- {
- "groupId": "com.ctre.phoenix6",
- "artifactId": "wpiapi-cpp",
- "version": "24.1.0",
- "libName": "CTRE_Phoenix6_WPI",
- "headerClassifier": "headers",
- "sharedLibrary": true,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "linuxathena"
- ],
- "simMode": "hwsim"
- },
- {
- "groupId": "com.ctre.phoenix6",
- "artifactId": "tools",
- "version": "24.1.0",
- "libName": "CTRE_PhoenixTools",
- "headerClassifier": "headers",
- "sharedLibrary": true,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "linuxathena"
- ],
- "simMode": "hwsim"
- },
- {
- "groupId": "com.ctre.phoenix6.sim",
- "artifactId": "wpiapi-cpp-sim",
- "version": "24.1.0",
- "libName": "CTRE_Phoenix6_WPISim",
- "headerClassifier": "headers",
- "sharedLibrary": true,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- },
- {
- "groupId": "com.ctre.phoenix6.sim",
- "artifactId": "tools-sim",
- "version": "24.1.0",
- "libName": "CTRE_PhoenixTools_Sim",
- "headerClassifier": "headers",
- "sharedLibrary": true,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- },
- {
- "groupId": "com.ctre.phoenix6.sim",
- "artifactId": "simTalonSRX",
- "version": "24.1.0",
- "libName": "CTRE_SimTalonSRX",
- "headerClassifier": "headers",
- "sharedLibrary": true,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- },
- {
- "groupId": "com.ctre.phoenix6.sim",
- "artifactId": "simTalonFX",
- "version": "24.1.0",
- "libName": "CTRE_SimTalonFX",
- "headerClassifier": "headers",
- "sharedLibrary": true,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- },
- {
- "groupId": "com.ctre.phoenix6.sim",
- "artifactId": "simVictorSPX",
- "version": "24.1.0",
- "libName": "CTRE_SimVictorSPX",
- "headerClassifier": "headers",
- "sharedLibrary": true,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- },
- {
- "groupId": "com.ctre.phoenix6.sim",
- "artifactId": "simPigeonIMU",
- "version": "24.1.0",
- "libName": "CTRE_SimPigeonIMU",
- "headerClassifier": "headers",
- "sharedLibrary": true,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- },
- {
- "groupId": "com.ctre.phoenix6.sim",
- "artifactId": "simCANCoder",
- "version": "24.1.0",
- "libName": "CTRE_SimCANCoder",
- "headerClassifier": "headers",
- "sharedLibrary": true,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- },
- {
- "groupId": "com.ctre.phoenix6.sim",
- "artifactId": "simProTalonFX",
- "version": "24.1.0",
- "libName": "CTRE_SimProTalonFX",
- "headerClassifier": "headers",
- "sharedLibrary": true,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- },
- {
- "groupId": "com.ctre.phoenix6.sim",
- "artifactId": "simProCANcoder",
- "version": "24.1.0",
- "libName": "CTRE_SimProCANcoder",
- "headerClassifier": "headers",
- "sharedLibrary": true,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- },
- {
- "groupId": "com.ctre.phoenix6.sim",
- "artifactId": "simProPigeon2",
- "version": "24.1.0",
- "libName": "CTRE_SimProPigeon2",
- "headerClassifier": "headers",
- "sharedLibrary": true,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "linuxx86-64",
- "osxuniversal"
- ],
- "simMode": "swsim"
- }
- ]
-}
+{
+ "fileName": "Phoenix6.json",
+ "name": "CTRE-Phoenix (v6)",
+ "version": "24.1.0",
+ "frcYear": 2024,
+ "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-frc2024-latest.json",
+ "conflictsWith": [
+ {
+ "uuid": "3fcf3402-e646-4fa6-971e-18afe8173b1a",
+ "errorMessage": "The combined Phoenix-6-And-5 vendordep is no longer supported. Please remove the vendordep and instead add both the latest Phoenix 6 vendordep and Phoenix 5 vendordep.",
+ "offlineFileName": "Phoenix6And5.json"
+ }
+ ],
+ "javaDependencies": [
+ {
+ "groupId": "com.ctre.phoenix6",
+ "artifactId": "wpiapi-java",
+ "version": "24.1.0"
+ }
+ ],
+ "jniDependencies": [
+ {
+ "groupId": "com.ctre.phoenix6",
+ "artifactId": "tools",
+ "version": "24.1.0",
+ "isJar": false,
+ "skipInvalidPlatforms": true,
+ "validPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "linuxathena"
+ ],
+ "simMode": "hwsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6.sim",
+ "artifactId": "tools-sim",
+ "version": "24.1.0",
+ "isJar": false,
+ "skipInvalidPlatforms": true,
+ "validPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6.sim",
+ "artifactId": "simTalonSRX",
+ "version": "24.1.0",
+ "isJar": false,
+ "skipInvalidPlatforms": true,
+ "validPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6.sim",
+ "artifactId": "simTalonFX",
+ "version": "24.1.0",
+ "isJar": false,
+ "skipInvalidPlatforms": true,
+ "validPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6.sim",
+ "artifactId": "simVictorSPX",
+ "version": "24.1.0",
+ "isJar": false,
+ "skipInvalidPlatforms": true,
+ "validPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6.sim",
+ "artifactId": "simPigeonIMU",
+ "version": "24.1.0",
+ "isJar": false,
+ "skipInvalidPlatforms": true,
+ "validPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6.sim",
+ "artifactId": "simCANCoder",
+ "version": "24.1.0",
+ "isJar": false,
+ "skipInvalidPlatforms": true,
+ "validPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6.sim",
+ "artifactId": "simProTalonFX",
+ "version": "24.1.0",
+ "isJar": false,
+ "skipInvalidPlatforms": true,
+ "validPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6.sim",
+ "artifactId": "simProCANcoder",
+ "version": "24.1.0",
+ "isJar": false,
+ "skipInvalidPlatforms": true,
+ "validPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6.sim",
+ "artifactId": "simProPigeon2",
+ "version": "24.1.0",
+ "isJar": false,
+ "skipInvalidPlatforms": true,
+ "validPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ }
+ ],
+ "cppDependencies": [
+ {
+ "groupId": "com.ctre.phoenix6",
+ "artifactId": "wpiapi-cpp",
+ "version": "24.1.0",
+ "libName": "CTRE_Phoenix6_WPI",
+ "headerClassifier": "headers",
+ "sharedLibrary": true,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "linuxathena"
+ ],
+ "simMode": "hwsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6",
+ "artifactId": "tools",
+ "version": "24.1.0",
+ "libName": "CTRE_PhoenixTools",
+ "headerClassifier": "headers",
+ "sharedLibrary": true,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "linuxathena"
+ ],
+ "simMode": "hwsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6.sim",
+ "artifactId": "wpiapi-cpp-sim",
+ "version": "24.1.0",
+ "libName": "CTRE_Phoenix6_WPISim",
+ "headerClassifier": "headers",
+ "sharedLibrary": true,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6.sim",
+ "artifactId": "tools-sim",
+ "version": "24.1.0",
+ "libName": "CTRE_PhoenixTools_Sim",
+ "headerClassifier": "headers",
+ "sharedLibrary": true,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6.sim",
+ "artifactId": "simTalonSRX",
+ "version": "24.1.0",
+ "libName": "CTRE_SimTalonSRX",
+ "headerClassifier": "headers",
+ "sharedLibrary": true,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6.sim",
+ "artifactId": "simTalonFX",
+ "version": "24.1.0",
+ "libName": "CTRE_SimTalonFX",
+ "headerClassifier": "headers",
+ "sharedLibrary": true,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6.sim",
+ "artifactId": "simVictorSPX",
+ "version": "24.1.0",
+ "libName": "CTRE_SimVictorSPX",
+ "headerClassifier": "headers",
+ "sharedLibrary": true,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6.sim",
+ "artifactId": "simPigeonIMU",
+ "version": "24.1.0",
+ "libName": "CTRE_SimPigeonIMU",
+ "headerClassifier": "headers",
+ "sharedLibrary": true,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6.sim",
+ "artifactId": "simCANCoder",
+ "version": "24.1.0",
+ "libName": "CTRE_SimCANCoder",
+ "headerClassifier": "headers",
+ "sharedLibrary": true,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6.sim",
+ "artifactId": "simProTalonFX",
+ "version": "24.1.0",
+ "libName": "CTRE_SimProTalonFX",
+ "headerClassifier": "headers",
+ "sharedLibrary": true,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6.sim",
+ "artifactId": "simProCANcoder",
+ "version": "24.1.0",
+ "libName": "CTRE_SimProCANcoder",
+ "headerClassifier": "headers",
+ "sharedLibrary": true,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ },
+ {
+ "groupId": "com.ctre.phoenix6.sim",
+ "artifactId": "simProPigeon2",
+ "version": "24.1.0",
+ "libName": "CTRE_SimProPigeon2",
+ "headerClassifier": "headers",
+ "sharedLibrary": true,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "linuxx86-64",
+ "osxuniversal"
+ ],
+ "simMode": "swsim"
+ }
+ ]
+}
diff --git a/vendordeps/REVLib.json b/vendordeps/REVLib.json
index 9e9b7c9..d739eb4 100644
--- a/vendordeps/REVLib.json
+++ b/vendordeps/REVLib.json
@@ -1,74 +1,74 @@
-{
- "fileName": "REVLib.json",
- "name": "REVLib",
- "version": "2024.2.0",
- "frcYear": "2024",
- "uuid": "3f48eb8c-50fe-43a6-9cb7-44c86353c4cb",
- "mavenUrls": [
- "https://maven.revrobotics.com/"
- ],
- "jsonUrl": "https://software-metadata.revrobotics.com/REVLib-2024.json",
- "javaDependencies": [
- {
- "groupId": "com.revrobotics.frc",
- "artifactId": "REVLib-java",
- "version": "2024.2.0"
- }
- ],
- "jniDependencies": [
- {
- "groupId": "com.revrobotics.frc",
- "artifactId": "REVLib-driver",
- "version": "2024.2.0",
- "skipInvalidPlatforms": true,
- "isJar": false,
- "validPlatforms": [
- "windowsx86-64",
- "windowsx86",
- "linuxarm64",
- "linuxx86-64",
- "linuxathena",
- "linuxarm32",
- "osxuniversal"
- ]
- }
- ],
- "cppDependencies": [
- {
- "groupId": "com.revrobotics.frc",
- "artifactId": "REVLib-cpp",
- "version": "2024.2.0",
- "libName": "REVLib",
- "headerClassifier": "headers",
- "sharedLibrary": false,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "windowsx86",
- "linuxarm64",
- "linuxx86-64",
- "linuxathena",
- "linuxarm32",
- "osxuniversal"
- ]
- },
- {
- "groupId": "com.revrobotics.frc",
- "artifactId": "REVLib-driver",
- "version": "2024.2.0",
- "libName": "REVLibDriver",
- "headerClassifier": "headers",
- "sharedLibrary": false,
- "skipInvalidPlatforms": true,
- "binaryPlatforms": [
- "windowsx86-64",
- "windowsx86",
- "linuxarm64",
- "linuxx86-64",
- "linuxathena",
- "linuxarm32",
- "osxuniversal"
- ]
- }
- ]
-}
+{
+ "fileName": "REVLib.json",
+ "name": "REVLib",
+ "version": "2024.2.0",
+ "frcYear": "2024",
+ "uuid": "3f48eb8c-50fe-43a6-9cb7-44c86353c4cb",
+ "mavenUrls": [
+ "https://maven.revrobotics.com/"
+ ],
+ "jsonUrl": "https://software-metadata.revrobotics.com/REVLib-2024.json",
+ "javaDependencies": [
+ {
+ "groupId": "com.revrobotics.frc",
+ "artifactId": "REVLib-java",
+ "version": "2024.2.0"
+ }
+ ],
+ "jniDependencies": [
+ {
+ "groupId": "com.revrobotics.frc",
+ "artifactId": "REVLib-driver",
+ "version": "2024.2.0",
+ "skipInvalidPlatforms": true,
+ "isJar": false,
+ "validPlatforms": [
+ "windowsx86-64",
+ "windowsx86",
+ "linuxarm64",
+ "linuxx86-64",
+ "linuxathena",
+ "linuxarm32",
+ "osxuniversal"
+ ]
+ }
+ ],
+ "cppDependencies": [
+ {
+ "groupId": "com.revrobotics.frc",
+ "artifactId": "REVLib-cpp",
+ "version": "2024.2.0",
+ "libName": "REVLib",
+ "headerClassifier": "headers",
+ "sharedLibrary": false,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "windowsx86",
+ "linuxarm64",
+ "linuxx86-64",
+ "linuxathena",
+ "linuxarm32",
+ "osxuniversal"
+ ]
+ },
+ {
+ "groupId": "com.revrobotics.frc",
+ "artifactId": "REVLib-driver",
+ "version": "2024.2.0",
+ "libName": "REVLibDriver",
+ "headerClassifier": "headers",
+ "sharedLibrary": false,
+ "skipInvalidPlatforms": true,
+ "binaryPlatforms": [
+ "windowsx86-64",
+ "windowsx86",
+ "linuxarm64",
+ "linuxx86-64",
+ "linuxathena",
+ "linuxarm32",
+ "osxuniversal"
+ ]
+ }
+ ]
+}
diff --git a/vendordeps/WPILibNewCommands.json b/vendordeps/WPILibNewCommands.json
index 67bf389..6bb55d1 100644
--- a/vendordeps/WPILibNewCommands.json
+++ b/vendordeps/WPILibNewCommands.json
@@ -1,38 +1,38 @@
-{
- "fileName": "WPILibNewCommands.json",
- "name": "WPILib-New-Commands",
- "version": "1.0.0",
- "uuid": "111e20f7-815e-48f8-9dd6-e675ce75b266",
- "frcYear": "2024",
- "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"
- ]
- }
- ]
-}
+{
+ "fileName": "WPILibNewCommands.json",
+ "name": "WPILib-New-Commands",
+ "version": "1.0.0",
+ "uuid": "111e20f7-815e-48f8-9dd6-e675ce75b266",
+ "frcYear": "2024",
+ "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"
+ ]
+ }
+ ]
+}