diff --git a/.github/workflows/gradle-build.yml b/.github/workflows/gradle-build.yml new file mode 100644 index 0000000..50ee8e3 --- /dev/null +++ b/.github/workflows/gradle-build.yml @@ -0,0 +1,59 @@ +# Gradle workflow to build the current project and generate a dependency graph for Dependabot Alerts. + +name: Gradle Dependencies and Build + +on: + push: + branches: [ "2025MainBranch" ] # Change to "main" when merged + pull_request: + branches: [ "2025MainBranch" ] # Change to "main" when merged + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - uses: actions/checkout@v4 + # Set up Java 17 JDK since the WPILib provided one isn't installed on this runner + # This will most likely change for a self-hosted runner + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies. + # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md + - name: Setup Gradle + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 + + - name: Build with Gradle Wrapper + # Set the working directory so gradlew and WPILib are in the right folder + # This will be removed in the future whenever this project is in the root folder + working-directory: ./2024-2025/main-bot + run: ./gradlew build + + dependency-submission: + + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - uses: actions/checkout@v4 + + # Set up Java 17 JDK since the WPILib provided one isn't installed on this runner + # This will most likely change for a self-hosted runner + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + # Generates and submits a dependency graph, enabling Dependabot Alerts for all project dependencies. + # See: https://github.com/gradle/actions/blob/main/dependency-submission/README.md + - name: Generate and submit dependency graph + uses: gradle/actions/dependency-submission@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 diff --git a/.github/workflows/superlinter.yml b/.github/workflows/superlinter.yml deleted file mode 100644 index a20e4e9..0000000 --- a/.github/workflows/superlinter.yml +++ /dev/null @@ -1,29 +0,0 @@ ---- -name: Super-Linter - -on: push - -jobs: - super-lint: - name: Super-Linter - runs-on: - - self-hosted - - Primary - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Run Super-Linter - uses: github/super-linter@v5 - env: - # Testing multiple folders and files - # Files to ignore: - # - gradlew - # - .gradle - # - WPILib-License.md - # Folders to ignore: - # - 2022-2023 - # - vendordeps - FILTER_REGEX_EXCLUDE: ".*2022-2023/.*|.*vendordeps/.*|.*gradlew|.*.gradle|.*WPILib-License.md.*" - DEFAULT_BRANCH: main - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/wpilib-build.yml b/.github/workflows/wpilib-build.yml deleted file mode 100644 index c866985..0000000 --- a/.github/workflows/wpilib-build.yml +++ /dev/null @@ -1,36 +0,0 @@ ---- -name: Build - -on: push - -jobs: - Build-Latest: - runs-on: - - self-hosted - - Primary - steps: - # Check out the code so the action can use it - - name: Checkout code - uses: actions/checkout@v4 - - - name: Build 2023-2024 - # Set the working directory so gradlew and WPILib are in the right folder - working-directory: ./2023-2024/main-bot - # Run gradlew to build the robot code with java home being what it is set to during manual runtime - # This machine should have Java 17 installed which is what WPILib is using for building with 2024 - run: ./gradlew build - Build-2022-2023: - runs-on: - - self-hosted - - Primary - steps: - # Check out the code so the action can use it - - name: Checkout code - uses: actions/checkout@v4 - - - name: Build 2022-2023 - working-directory: ./2022-2023/main-bot - run: ./gradlew build - - -# I have no idea if this will work but this is just to test to see if it's possible and to get used to using actions diff --git a/.gitignore b/.gitignore index 4835bef..a0a205e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,10 @@ # .gitignore # Ingore File For Git +*.gradle/ +*.wpilib/ +*bin/ + # -----=====[ IDEs ]=====----- # # VSCode @@ -148,9 +152,37 @@ dmypy.json # Pyre type checker .pyre/ +# -----=====[ Java ]=====----- # +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + # -----=====[ Misc ]=====----- # # MacOS Finder Cache # >:( *.DS_Store - +*.dat +*.hoot +*.lock \ No newline at end of file diff --git a/2022-2023/main-bot/.gradle/7.5.1/checksums/checksums.lock b/2022-2023/main-bot/.gradle/7.5.1/checksums/checksums.lock deleted file mode 100755 index d17e810..0000000 Binary files a/2022-2023/main-bot/.gradle/7.5.1/checksums/checksums.lock and /dev/null differ diff --git a/2022-2023/main-bot/.gradle/7.5.1/checksums/md5-checksums.bin b/2022-2023/main-bot/.gradle/7.5.1/checksums/md5-checksums.bin deleted file mode 100755 index 2f8a567..0000000 Binary files a/2022-2023/main-bot/.gradle/7.5.1/checksums/md5-checksums.bin and /dev/null differ diff --git a/2022-2023/main-bot/.gradle/7.5.1/checksums/sha1-checksums.bin b/2022-2023/main-bot/.gradle/7.5.1/checksums/sha1-checksums.bin deleted file mode 100755 index f874a97..0000000 Binary files a/2022-2023/main-bot/.gradle/7.5.1/checksums/sha1-checksums.bin and /dev/null differ diff --git a/2022-2023/main-bot/.gradle/7.5.1/dependencies-accessors/dependencies-accessors.lock b/2022-2023/main-bot/.gradle/7.5.1/dependencies-accessors/dependencies-accessors.lock deleted file mode 100755 index 4e31113..0000000 Binary files a/2022-2023/main-bot/.gradle/7.5.1/dependencies-accessors/dependencies-accessors.lock and /dev/null differ diff --git a/2022-2023/main-bot/.gradle/7.5.1/executionHistory/executionHistory.bin b/2022-2023/main-bot/.gradle/7.5.1/executionHistory/executionHistory.bin deleted file mode 100755 index b53bfdc..0000000 Binary files a/2022-2023/main-bot/.gradle/7.5.1/executionHistory/executionHistory.bin and /dev/null differ diff --git a/2022-2023/main-bot/.gradle/7.5.1/executionHistory/executionHistory.lock b/2022-2023/main-bot/.gradle/7.5.1/executionHistory/executionHistory.lock deleted file mode 100755 index a8b1257..0000000 Binary files a/2022-2023/main-bot/.gradle/7.5.1/executionHistory/executionHistory.lock and /dev/null differ diff --git a/2022-2023/main-bot/.gradle/7.5.1/fileChanges/last-build.bin b/2022-2023/main-bot/.gradle/7.5.1/fileChanges/last-build.bin deleted file mode 100755 index f76dd23..0000000 Binary files a/2022-2023/main-bot/.gradle/7.5.1/fileChanges/last-build.bin and /dev/null differ diff --git a/2022-2023/main-bot/.gradle/7.5.1/fileHashes/fileHashes.bin b/2022-2023/main-bot/.gradle/7.5.1/fileHashes/fileHashes.bin deleted file mode 100755 index 1b0c1b1..0000000 Binary files a/2022-2023/main-bot/.gradle/7.5.1/fileHashes/fileHashes.bin and /dev/null differ diff --git a/2022-2023/main-bot/.gradle/7.5.1/fileHashes/fileHashes.lock b/2022-2023/main-bot/.gradle/7.5.1/fileHashes/fileHashes.lock deleted file mode 100755 index a69daf0..0000000 Binary files a/2022-2023/main-bot/.gradle/7.5.1/fileHashes/fileHashes.lock and /dev/null differ diff --git a/2022-2023/main-bot/.gradle/7.5.1/fileHashes/resourceHashesCache.bin b/2022-2023/main-bot/.gradle/7.5.1/fileHashes/resourceHashesCache.bin deleted file mode 100755 index 7df2b98..0000000 Binary files a/2022-2023/main-bot/.gradle/7.5.1/fileHashes/resourceHashesCache.bin and /dev/null differ diff --git a/2022-2023/main-bot/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/2022-2023/main-bot/.gradle/buildOutputCleanup/buildOutputCleanup.lock deleted file mode 100755 index f4c0a08..0000000 Binary files a/2022-2023/main-bot/.gradle/buildOutputCleanup/buildOutputCleanup.lock and /dev/null differ diff --git a/2022-2023/main-bot/.gradle/buildOutputCleanup/outputFiles.bin b/2022-2023/main-bot/.gradle/buildOutputCleanup/outputFiles.bin deleted file mode 100755 index eae504c..0000000 Binary files a/2022-2023/main-bot/.gradle/buildOutputCleanup/outputFiles.bin and /dev/null differ diff --git a/2022-2023/main-bot/bin/main/frc/components/SwerveDrive.class b/2022-2023/main-bot/bin/main/frc/components/SwerveDrive.class index b0bfedf..084cf57 100644 Binary files a/2022-2023/main-bot/bin/main/frc/components/SwerveDrive.class and b/2022-2023/main-bot/bin/main/frc/components/SwerveDrive.class differ diff --git a/2022-2023/main-bot/bin/main/frc/components/autonomous/DriveState2.class b/2022-2023/main-bot/bin/main/frc/components/autonomous/DriveState2.class index 08983c3..60593cc 100644 Binary files a/2022-2023/main-bot/bin/main/frc/components/autonomous/DriveState2.class and b/2022-2023/main-bot/bin/main/frc/components/autonomous/DriveState2.class differ diff --git a/2022-2023/main-bot/bin/main/frc/components/autonomous/DriveState3.class b/2022-2023/main-bot/bin/main/frc/components/autonomous/DriveState3.class index 4ebecb7..70794fc 100644 Binary files a/2022-2023/main-bot/bin/main/frc/components/autonomous/DriveState3.class and b/2022-2023/main-bot/bin/main/frc/components/autonomous/DriveState3.class differ diff --git a/2022-2023/main-bot/bin/main/frc/robot/Utility.class b/2022-2023/main-bot/bin/main/frc/robot/Utility.class index f9d72fb..5dde4a6 100644 Binary files a/2022-2023/main-bot/bin/main/frc/robot/Utility.class and b/2022-2023/main-bot/bin/main/frc/robot/Utility.class differ diff --git a/2022-2023/main-bot/gradle/wrapper/gradle-wrapper.jar b/2022-2023/main-bot/gradle/wrapper/gradle-wrapper.jar deleted file mode 100755 index 249e583..0000000 Binary files a/2022-2023/main-bot/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/2023-2024/main-bot/gradle/wrapper/gradle-wrapper.jar b/2023-2024/main-bot/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 7f93135..0000000 Binary files a/2023-2024/main-bot/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/2024-2025/FreshmanProjectBots/DontOverthinkIt/.wpilib/wpilib_preferences.json b/2024-2025/FreshmanProjectBots/DontOverthinkIt/.wpilib/wpilib_preferences.json new file mode 100644 index 0000000..a5ebb07 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/DontOverthinkIt/.wpilib/wpilib_preferences.json @@ -0,0 +1,6 @@ +{ + "enableCppIntellisense": false, + "currentLanguage": "java", + "projectYear": "2024", + "teamNumber": 5098 +} \ No newline at end of file diff --git a/2024-2025/FreshmanProjectBots/DontOverthinkIt/WPILib-License.md b/2024-2025/FreshmanProjectBots/DontOverthinkIt/WPILib-License.md new file mode 100644 index 0000000..e7cd597 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/DontOverthinkIt/WPILib-License.md @@ -0,0 +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. diff --git a/2024-2025/FreshmanProjectBots/DontOverthinkIt/build.gradle b/2024-2025/FreshmanProjectBots/DontOverthinkIt/build.gradle new file mode 100644 index 0000000..1e8da00 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/DontOverthinkIt/build.gradle @@ -0,0 +1,101 @@ +plugins { + id "java" + id "edu.wpi.first.GradleRIO" version "2024.2.1" +} + +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 = false + +// Defining my dependencies. In this case, WPILib (+ friends), and vendor libraries. +// Also defines JUnit 5. +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' +} + +test { + useJUnitPlatform() + systemProperty 'junit.jupiter.extensions.autodetection.enabled', 'true' +} + +// Simulation configuration (e.g. environment variables). +wpi.sim.addGui().defaultEnabled = true +wpi.sim.addDriverstation() + +// Setting up my Jar File. In this case, adding all libraries into the main jar ('fat 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' +} diff --git a/2024-2025/FreshmanProjectBots/DontOverthinkIt/gradle/wrapper/gradle-wrapper.properties b/2024-2025/FreshmanProjectBots/DontOverthinkIt/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..7015f6b --- /dev/null +++ b/2024-2025/FreshmanProjectBots/DontOverthinkIt/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=permwrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=permwrapper/dists diff --git a/2024-2025/FreshmanProjectBots/DontOverthinkIt/gradlew b/2024-2025/FreshmanProjectBots/DontOverthinkIt/gradlew new file mode 100644 index 0000000..1aa94a4 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/DontOverthinkIt/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/2024-2025/FreshmanProjectBots/DontOverthinkIt/gradlew.bat b/2024-2025/FreshmanProjectBots/DontOverthinkIt/gradlew.bat new file mode 100644 index 0000000..6689b85 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/DontOverthinkIt/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/2024-2025/FreshmanProjectBots/DontOverthinkIt/settings.gradle b/2024-2025/FreshmanProjectBots/DontOverthinkIt/settings.gradle new file mode 100644 index 0000000..3e30f84 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/DontOverthinkIt/settings.gradle @@ -0,0 +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"); diff --git a/2024-2025/FreshmanProjectBots/DontOverthinkIt/src/main/deploy/example.txt b/2024-2025/FreshmanProjectBots/DontOverthinkIt/src/main/deploy/example.txt new file mode 100644 index 0000000..bb82515 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/DontOverthinkIt/src/main/deploy/example.txt @@ -0,0 +1,3 @@ +Files placed in this directory will be deployed to the RoboRIO into the +'deploy' directory in the home folder. Use the 'Filesystem.getDeployDirectory' wpilib function +to get a proper path relative to the deploy directory. \ No newline at end of file diff --git a/2024-2025/FreshmanProjectBots/DontOverthinkIt/src/main/java/frc/Components/Drive.java b/2024-2025/FreshmanProjectBots/DontOverthinkIt/src/main/java/frc/Components/Drive.java new file mode 100644 index 0000000..946bd8a --- /dev/null +++ b/2024-2025/FreshmanProjectBots/DontOverthinkIt/src/main/java/frc/Components/Drive.java @@ -0,0 +1,12 @@ +package frc.Components; +import com.ctre.phoenix6.hardware.TalonFX; +// import com.ctre.phoenix6.hardware.TalonSRX; +// import com.ctre.phoenix6.motorcontrol.ControlMode; +// import com.ctre.phoenix6.motorcontrol.can.TalonSRX; + +public class Drive { + private TalonFX motor; + + public Drive(int motorId) { motor = new TalonFX(motorId); } + public void MoveMotor(double power) { TalonFX leftMotor1 = new TalonFX(1); } +} \ No newline at end of file diff --git a/2024-2025/FreshmanProjectBots/DontOverthinkIt/src/main/java/frc/Controllers/Xbox.java b/2024-2025/FreshmanProjectBots/DontOverthinkIt/src/main/java/frc/Controllers/Xbox.java new file mode 100644 index 0000000..d8462f2 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/DontOverthinkIt/src/main/java/frc/Controllers/Xbox.java @@ -0,0 +1,393 @@ +package frc.Controllers; + +import edu.wpi.first.wpilibj.GenericHID.RumbleType; +import edu.wpi.first.wpilibj.XboxController; + +/** + * This class is used to create an Xbox controller object. + *

+ * This class uses the {@code XboxController} class from the wpilibj library. + *

+ *

+ * This uses a deadband that can be set if needed. This helps control drift. + * This value can be in a range of 0 to 1. The higher the value, the more the + * stick has to move to register. This value is set in the constructor and is + * set alongside the controller ID. As a note: The deadband is only applied + * to the joystick axes. + *

+ * + * @see LogitechF310 + * @see PS4 + * + * @see edu.wpi.first.wpilibj.XboxController + */ +public class Xbox { + + /** + * The controller object. + * In this case, a {@code XboxController} object. + */ + private XboxController controller; + + /** + * The deadband value. + */ + private double deadBand; + + /** + * Constructor for the Xbox class. + *

+ * This constructor is used to create a LogitechF310 object. + * This takes in the controller ID and the deadband value. + *

+ * + * @param id Controller ID (Port) + * @param deadBandValue Deadband value + */ + public Xbox(final int id, final double deadBandValue) { + controller = new XboxController(id); + deadBand = deadBandValue; + } + + // Deadband Method // + + // Although this isn't really needed for newer controllers, + // it's still here just in case one might develop drift + + /** + * Method for setting the deadband of the controller on the X and Y axes. + *

+ * This sets a threshold the joystick must pass before registering a value. + * This value can be in a range of 0 to 1. The higher the value, + * the more the joystick has to move to register. + *

+ * + * @return Deadbanded value + * + * @param value Value to be deadbanded + */ + private double deadBand(final double value) { + return Math.abs(value) < deadBand ? 0 : value; + } + + // Joystick Methods // + + /** + * Method for returning the X value of the left joystick. + * + * @return X value of the left joystick + * + * @see Xbox#getRightX + * @see Xbox#getRightY + * @see Xbox#getLeftY + */ + public double getLeftX() { return deadBand(controller.getLeftX()); } + + /** + * Method for returning the Y value of the left joystick. + * + * @return Y value of the left joystick + * + * @see Xbox#getRightX + * @see Xbox#getRightY + * @see Xbox#getLeftX + */ + public double getLeftY() { return deadBand(controller.getLeftY()); } + + /** + * Method for returning the X value of the right joystick. + * + * @return X value of the right joystick + * + * @see Xbox#getRightY + * @see Xbox#getLeftX + * @see Xbox#getLeftY + */ + public double getRightX() { return deadBand(controller.getRightX()); } + + /** + * Method for returning the Y value of the right joystick. + * + * @return Y value of the right joystick + * + * @see Xbox#getRightX + * @see Xbox#getLeftX + * @see Xbox#getLeftY + */ + public double getRightY() { return deadBand(controller.getRightY()); } + + // Trigger Methods // + + /** + * Method for returning the value of the left trigger. + * + * @return value of the left trigger + * + * @see Xbox#getRightTrigger + */ + public double getLeftTrigger() { return controller.getLeftTriggerAxis(); } + + /** + * Method for returning the value of the right trigger. + * + * @return value of the right trigger + * + * @see Xbox#getLeftTrigger + */ + public double getRightTrigger() { return controller.getRightTriggerAxis(); } + + // Button Methods // + + /** + * Method for returning the value of the A button. + * + * @return value of the A button + * + * @see Xbox#getBButton + * @see Xbox#getXButton + * @see Xbox#getYButton + */ + public boolean getAButton() { return controller.getAButton(); } + + /** + * Method for returning the value of the B button. + * + * @return value of the B button + * + * @see Xbox#getAButton + * @see Xbox#getXButton + * @see Xbox#getYButton + */ + public boolean getBButton() { return controller.getBButton(); } + + /** + * Method for returning the value of the X button. + * + * @return value of the X button + * + * @see Xbox#getAButton + * @see Xbox#getBButton + * @see Xbox#getYButton + */ + public boolean getXButton() { return controller.getXButton(); } + + /** + * Method for returning the value of the Y button. + * + * @return value of the Y button + * + * @see Xbox#getAButton + * @see Xbox#getBButton + * @see Xbox#getXButton + */ + public boolean getYButton() { return controller.getYButton(); } + + /** + * Method for returning the value of the start button. + * + * @return value of the start button + * + * @see Xbox#getBackButton + */ + public boolean getStartButton() { return controller.getStartButton(); } + + /** + * Method for returning the value of the back button. + * + * @return value of the back button + * + * @see Xbox#getStartButton + */ + public boolean getBackButton() { return controller.getBackButton(); } + + /** + * Method for returning the value of the left bumper. + * + * @return value of the left bumper + * + * @see Xbox#getRightBumper + */ + public boolean getLeftBumper() { return controller.getLeftBumper(); } + + /** + * Method for returning the value of the right bumper. + * + * @return value of the right bumper + * + * @see Xbox#getLeftBumper + */ + public boolean getRightBumper() { return controller.getRightBumper(); } + + /** + * Method for returning the value of the left stick button. + * + * @return value of the left stick button + * + * @see Xbox#getRightStickButton + */ + public boolean getLeftStickButton() { + return controller.getLeftStickButton(); + } + + /** + * Method for returning the value of the right stick button. + * + * @return value of the right stick button + * + * @see Xbox#getLeftStickButton + */ + public boolean getRightStickButton() { + return controller.getRightStickButton(); + } + + // D-Pad Methods // + + public enum DPad { + /** + * Up on the D-Pad. + */ + up, + + /** + * Down on the D-Pad. + */ + down, + + /** + * Right on the D-Pad. + */ + left, + + /** + * Left on the D-Pad. + */ + right, + + /** + * Up-Right on the D-Pad. + */ + upright, + + /** + * Up-Left on the D-Pad. + */ + upleft, + + /** + * Down-Right on the D-Pad. + */ + downright, + + /** + * Down-Left on the D-Pad. + */ + downleft, + + /** + * No direction on the D-Pad. + */ + none + } + + /** + * Upright D-Pad POV value. + */ + private static final int DPAD_UPRIGHT = 45; + + /** + * Right D-Pad POV value. + */ + private static final int DPAD_RIGHT = 90; + + /** + * Downright D-Pad POV value. + */ + private static final int DPAD_DOWNRIGHT = 135; + + /** + * Down POV D-Pad value. + */ + private static final int DPAD_DOWN = 180; + + /** + * Downleft D-Pad POV value. + */ + private static final int DPAD_DOWNLEFT = 225; + + /** + * Left D-Pad POV value. + */ + private static final int DPAD_LEFT = 270; + + /** + * Upleft D-Pad POV value. + */ + private static final int DPAD_UPLEFT = 315; + + /** + * Up D-Pad POV value. + */ + private static final int DPAD_UP = 360; + + /** + * Method for returning the value of the D-Pad. + * + * @return value of the D-Pad + * + * @see Xbox.DPad + */ + public DPad getDPad() { + switch (controller.getPOV()) { + case 0: + return DPad.up; + case DPAD_UPRIGHT: + return DPad.upright; + case DPAD_RIGHT: + return DPad.right; + case DPAD_DOWNRIGHT: + return DPad.downright; + case DPAD_DOWN: + return DPad.down; + case DPAD_DOWNLEFT: + return DPad.downleft; + case DPAD_LEFT: + return DPad.left; + case DPAD_UPLEFT: + return DPad.upleft; + case DPAD_UP: + return DPad.up; + default: + return DPad.none; + } + } + + // Rumble Methods // + + /** + * Method for setting the rumble of the controller. + * + * @param type type of rumble to set + * @param value value to set the rumble to + * + * @see edu.wpi.first.wpilibj.GenericHID.RumbleType + */ + public void setRumble(final RumbleType type, final double value) { + controller.setRumble(type, value); + } + + // General Methods // + + /** + * Method for checking if the controller is connected. + * + * @return true if the controller is connected, false if not + */ + public boolean isConnected() { return (controller.isConnected()); } + + /** + * Method for getting the name of the controller. + * + * @return name of the controller + */ + public String getName() { return controller.getName(); } +} diff --git a/2024-2025/FreshmanProjectBots/DontOverthinkIt/src/main/java/frc/robot/Main.java b/2024-2025/FreshmanProjectBots/DontOverthinkIt/src/main/java/frc/robot/Main.java new file mode 100644 index 0000000..8776e5d --- /dev/null +++ b/2024-2025/FreshmanProjectBots/DontOverthinkIt/src/main/java/frc/robot/Main.java @@ -0,0 +1,25 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package 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/2024-2025/FreshmanProjectBots/DontOverthinkIt/src/main/java/frc/robot/Robot.java b/2024-2025/FreshmanProjectBots/DontOverthinkIt/src/main/java/frc/robot/Robot.java new file mode 100644 index 0000000..e8946ec --- /dev/null +++ b/2024-2025/FreshmanProjectBots/DontOverthinkIt/src/main/java/frc/robot/Robot.java @@ -0,0 +1,64 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot; + +import edu.wpi.first.wpilibj.TimedRobot; +import frc.Components.Drive; + +/** + * The VM is configured to automatically run this class, and to call the + * functions corresponding to each mode, as described in the TimedRobot + * documentation. If you change the name of this class or the package after + * creating this project, you must also update the build.gradle file in the + * project. + */ +public class Robot extends TimedRobot { + /** + * This function is run when the robot is first started up and should be used + * for any initialization code. + */ + + Drive drive; + + @Override + public void robotInit() { + drive = new Drive(0); // Heyyyy bestie this is a temporary ID + } + + @Override + public void robotPeriodic() {} + + @Override + public void autonomousInit() {} + + @Override + public void autonomousPeriodic() {} + + @Override + public void teleopInit() {} + + @Override + public void teleopPeriodic() {} + + @Override + public void disabledInit() {} + + @Override + public void disabledPeriodic() {} + + @Override + public void testInit() {} + + @Override + public void testPeriodic() { + drive.MoveMotor(0.5); + } + + @Override + public void simulationInit() {} + + @Override + public void simulationPeriodic() {} +} diff --git a/2024-2025/FreshmanProjectBots/DontOverthinkIt/vendordeps/Phoenix6.json b/2024-2025/FreshmanProjectBots/DontOverthinkIt/vendordeps/Phoenix6.json new file mode 100644 index 0000000..0322385 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/DontOverthinkIt/vendordeps/Phoenix6.json @@ -0,0 +1,339 @@ +{ + "fileName": "Phoenix6.json", + "name": "CTRE-Phoenix (v6)", + "version": "24.3.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.3.0" + } + ], + "jniDependencies": [ + { + "groupId": "com.ctre.phoenix6", + "artifactId": "tools", + "version": "24.3.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "tools-sim", + "version": "24.3.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simTalonSRX", + "version": "24.3.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simTalonFX", + "version": "24.3.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simVictorSPX", + "version": "24.3.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simPigeonIMU", + "version": "24.3.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simCANCoder", + "version": "24.3.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProTalonFX", + "version": "24.3.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANcoder", + "version": "24.3.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProPigeon2", + "version": "24.3.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + } + ], + "cppDependencies": [ + { + "groupId": "com.ctre.phoenix6", + "artifactId": "wpiapi-cpp", + "version": "24.3.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.3.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.3.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.3.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.3.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.3.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.3.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.3.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.3.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.3.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.3.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.3.0", + "libName": "CTRE_SimProPigeon2", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + } + ] +} \ No newline at end of file diff --git a/2024-2025/FreshmanProjectBots/DontOverthinkIt/vendordeps/WPILibNewCommands.json b/2024-2025/FreshmanProjectBots/DontOverthinkIt/vendordeps/WPILibNewCommands.json new file mode 100644 index 0000000..67bf389 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/DontOverthinkIt/vendordeps/WPILibNewCommands.json @@ -0,0 +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" + ] + } + ] +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/WPILib-License.md b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/WPILib-License.md new file mode 100644 index 0000000..e7cd597 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/WPILib-License.md @@ -0,0 +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. diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/build.gradle b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/build.gradle new file mode 100644 index 0000000..b9f0e50 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/build.gradle @@ -0,0 +1,104 @@ +plugins { + id "java" + id "edu.wpi.first.GradleRIO" version "2025.2.1" +} + +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' + deleteOldFiles = false // Change to true to delete files on roboRIO that no + // longer exist in deploy directory of this project + } + } + } + } +} + +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 = false + +// Defining my dependencies. In this case, WPILib (+ friends), and vendor libraries. +// Also defines JUnit 5. +dependencies { + annotationProcessor wpi.java.deps.wpilibAnnotations() + implementation wpi.java.deps.wpilib() + implementation wpi.java.vendor.java() + + roborioDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.roborio) + roborioDebug wpi.java.vendor.jniDebug(wpi.platforms.roborio) + + 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' +} + +test { + useJUnitPlatform() + systemProperty 'junit.jupiter.extensions.autodetection.enabled', 'true' +} + +// Simulation configuration (e.g. environment variables). +wpi.sim.addGui().defaultEnabled = true +wpi.sim.addDriverstation() + +// Setting up my Jar File. In this case, adding all libraries into the main jar ('fat 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' +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/gradle/wrapper/gradle-wrapper.properties b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..8e975a5 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=permwrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=permwrapper/dists diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/gradlew b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/gradlew new file mode 100644 index 0000000..f5feea6 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/gradlew @@ -0,0 +1,252 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/gradlew.bat b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/gradlew.bat new file mode 100644 index 0000000..9b42019 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/settings.gradle b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/settings.gradle new file mode 100644 index 0000000..3bc070a --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/settings.gradle @@ -0,0 +1,30 @@ +import org.gradle.internal.os.OperatingSystem + +pluginManagement { + repositories { + mavenLocal() + gradlePluginPortal() + String frcYear = '2025' + 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/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/deploy/example.txt b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/deploy/example.txt new file mode 100644 index 0000000..bb82515 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/deploy/example.txt @@ -0,0 +1,3 @@ +Files placed in this directory will be deployed to the RoboRIO into the +'deploy' directory in the home folder. Use the 'Filesystem.getDeployDirectory' wpilib function +to get a proper path relative to the deploy directory. \ No newline at end of file diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/Constants.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/Constants.java new file mode 100644 index 0000000..768c0cb --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/Constants.java @@ -0,0 +1,27 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot; + +/** + * 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 class OperatorConstants { + public static final int kDriverControllerPort = 0; + public static final int motorId = 0; + } + + public static class DriveConstants { + public static final int kFLMotorId = 3; + public static final int kFRMotorId = 1; + public static final int kBLMotorId = 4; + public static final int kBRMotorId = 2; + } +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/Main.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/Main.java new file mode 100644 index 0000000..8776e5d --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/Main.java @@ -0,0 +1,25 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package 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/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/Robot.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/Robot.java new file mode 100644 index 0000000..91e75cd --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/Robot.java @@ -0,0 +1,104 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot; + +import edu.wpi.first.wpilibj.TimedRobot; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.CommandScheduler; + +/** + * The VM is configured to automatically run this class, and to call the functions corresponding to + * each mode, as described in the TimedRobot documentation. If you change the name of this class or + * the package after creating this project, you must also update the build.gradle file in the + * project. + */ +public class Robot extends TimedRobot { + + private Command m_autonomousCommand; + + private RobotContainer m_robotContainer; + + /** + * This function is run when the robot is first started up and should be used for any + * initialization code. + */ + @Override + public void robotInit() { + // Instantiate our RobotContainer. This will perform all our button bindings, and put our + // autonomous chooser on the dashboard. + m_robotContainer = new RobotContainer(); + } + + /** + * This function is called every 20 ms, no matter the mode. Use this for items like diagnostics + * that you want ran during disabled, autonomous, teleoperated and test. + * + *

This runs after the mode specific periodic functions, but before LiveWindow and + * SmartDashboard integrated updating. + */ + @Override + public void robotPeriodic() { + // Runs the Scheduler. This is responsible for polling buttons, adding newly-scheduled + // commands, running already-scheduled commands, removing finished or interrupted commands, + // and running subsystem periodic() methods. This must be called from the robot's periodic + // block in order for anything in the Command-based framework to work. + CommandScheduler.getInstance().run(); + } + + /** This function is called once each time the robot enters Disabled mode. */ + @Override + public void disabledInit() {} + + @Override + public void disabledPeriodic() {} + + /** This autonomous runs the autonomous command selected by your {@link RobotContainer} class. */ + @Override + public void autonomousInit() { + // m_autonomousCommand = m_robotContainer.getAutonomousCommand(); + + // schedule the autonomous command (example) + if (m_autonomousCommand != null) { + m_autonomousCommand.schedule(); + } + } + + /** This function is called periodically during autonomous. */ + @Override + public void autonomousPeriodic() {} + + @Override + public void teleopInit() { + // This makes sure that the autonomous stops running when + // teleop starts running. If you want the autonomous to + // continue until interrupted by another command, remove + // this line or comment it out. + if (m_autonomousCommand != null) { + m_autonomousCommand.cancel(); + } + } + + /** This function is called periodically during operator control. */ + @Override + public void teleopPeriodic() {} + + @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/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/RobotContainer.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/RobotContainer.java new file mode 100644 index 0000000..c0a0b59 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/RobotContainer.java @@ -0,0 +1,92 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot; + +import frc.robot.Constants.OperatorConstants; +import frc.robot.Constants.DriveConstants; +import frc.robot.commands.Autos; +import frc.robot.commands.ExampleCommand; +import frc.robot.subsystems.DriveSubsystem; +import frc.robot.subsystems.ExampleSubsystem; +import edu.wpi.first.wpilibj.XboxController; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.RunCommand; +import edu.wpi.first.wpilibj2.command.button.CommandXboxController; +import edu.wpi.first.wpilibj2.command.button.JoystickButton; +import edu.wpi.first.wpilibj2.command.button.Trigger; +import frc.robot.controllers.Xbox; + +/** + * This class is where the bulk of the robot should be declared. Since Command-based is a + * "declarative" paradigm, very little robot logic should actually be handled in the {@link Robot} + * periodic methods (other than the scheduler calls). Instead, the structure of the robot (including + * subsystems, commands, and trigger mappings) should be declared here. + */ +public class RobotContainer { + // The robot's subsystems and commands are defined here... + // private final ExampleSubsystem m_exampleSubsystem = new ExampleSubsystem(OperatorConstants.motorId); + private final DriveSubsystem m_driveSubsystem = new DriveSubsystem(DriveConstants.kFLMotorId, DriveConstants.kFRMotorId, DriveConstants.kBLMotorId, DriveConstants.kBRMotorId); + + // Replace with CommandPS4Controller or CommandJoystick if needed + private final CommandXboxController m_driverController = + new CommandXboxController(OperatorConstants.kDriverControllerPort); + + // Creation of normal controller + // private final XboxController normalXboxController = new XboxController(0); + + /** The container for the robot. Contains subsystems, OI devices, and commands. */ + public RobotContainer() { + // Configure the trigger bindings + configureBindings(); + } + + /** + * Use this method to define your trigger->command mappings. Triggers can be created via the + * {@link Trigger#Trigger(java.util.function.BooleanSupplier)} constructor with an arbitrary + * predicate, or via the named factories in {@link + * edu.wpi.first.wpilibj2.command.button.CommandGenericHID}'s subclasses for {@link + * CommandXboxController Xbox}/{@link edu.wpi.first.wpilibj2.command.button.CommandPS4Controller + * PS4} controllers or {@link edu.wpi.first.wpilibj2.command.button.CommandJoystick Flight + * joysticks}. + */ + private void configureBindings() { + // Schedule `ExampleCommand` when `exampleCondition` changes to `true` + // new Trigger(m_exampleSubsystem::exampleCondition) + // .onTrue(new ExampleCommand(m_exampleSubsystem)); + System.out.println("Bindings Configured ********************************************"); + + // Controls using the command based xbox controller + // m_driverController.leftTrigger().whileTrue(m_driveSubsystem.setMotorVoltageCommand(m_driverController.getLeftX(), m_driverController.getRawAxis(3), m_driverController.getRawAxis(4))); + // m_driverController.rightTrigger().whileTrue(m_driveSubsystem.setMotorVoltageCommand(m_driverController.getRawAxis(2), m_driverController.getRawAxis(3), m_driverController.getRawAxis(4))); + // m_driverController.rightStick().whileTrue(m_driveSubsystem.setMotorVoltageCommand(m_driverController.getRawAxis(2), m_driverController.getRawAxis(3), m_driverController.getRawAxis(4))); + m_driveSubsystem.setDefaultCommand( + new RunCommand( + () -> + m_driveSubsystem.setMotorVoltage( + m_driverController.getLeftTriggerAxis(), + m_driverController.getRightTriggerAxis(), + m_driverController.getRightX()), + m_driveSubsystem)); + + // Controls using the normal xbox controller + // Trigger leftTriggerActivated = new JoystickButton(normalXboxController, XboxController.Axis.kLeftTrigger.value); + // leftTriggerActivated.whileTrue(m_driveSubsystem.setMotorVoltageCommand(normalXboxController.getRawAxis(2), normalXboxController.getRawAxis(3), normalXboxController.getRawAxis(4))); + + + // Schedule `exampleMethodCommand` when the Xbox controller's B button is pressed, + // cancelling on release. + // m_driverController.b().whileTrue(m_exampleSubsystem.exampleMethodCommand()); + } + + /** + * Use this to pass the autonomous command to the main {@link Robot} class. + * + * @return the command to run in autonomous + */ + // public Command getAutonomousCommand() { + // // An example command will be run in autonomous + // return Autos.exampleAuto(m_exampleSubsystem); + // } +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/commands/Autos.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/commands/Autos.java new file mode 100644 index 0000000..107aad7 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/commands/Autos.java @@ -0,0 +1,20 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot.commands; + +import frc.robot.subsystems.ExampleSubsystem; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.Commands; + +public final class Autos { + /** Example static factory for an autonomous command. */ + public static Command exampleAuto(ExampleSubsystem subsystem) { + return Commands.sequence(subsystem.exampleMethodCommand(), new ExampleCommand(subsystem)); + } + + private Autos() { + throw new UnsupportedOperationException("This is a utility class!"); + } +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/commands/ExampleCommand.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/commands/ExampleCommand.java new file mode 100644 index 0000000..d609d82 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/commands/ExampleCommand.java @@ -0,0 +1,63 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot.commands; + +import frc.robot.subsystems.ExampleSubsystem; +import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; +import edu.wpi.first.wpilibj2.command.Command; + +import com.ctre.phoenix.motorcontrol.ControlMode; +import com.ctre.phoenix.motorcontrol.TalonSRXControlMode; +import com.ctre.phoenix.motorcontrol.can.TalonSRX; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;; + +/** An example command that uses an example subsystem. */ + + +public class ExampleCommand extends Command { + @SuppressWarnings({"PMD.UnusedPrivateField", "PMD.SingularField"}) + private final ExampleSubsystem m_subsystem; + // private final TalonSRX FLMotor; + // private final TalonSRX BLMotor; + + + /** + * Creates a new ExampleCommand. + * + * @param subsystem The subsystem used by this command. + */ + public ExampleCommand(ExampleSubsystem subsystem ) { + m_subsystem = subsystem; + // FLMotor = new TalonSRX(FLId); + // BLMotor = new TalonSRX(BLId); + // Use addRequirements() here to declare subsystem dependencies. + addRequirements(subsystem); + } + + // Called when the command is initially scheduled. + @Override + public void initialize() { + } + + // Called every time the scheduler runs while the command is scheduled. + @Override + public void execute() { + + // double leftFrontMotorInput = rightTrigger + jfioejo + hiofeaj; + + // FLMotor.set(ControlMode.PercentOutput, leftFrontMotorInput); + // BLMotor.set(ControlMode.PercentOutput, leftTrigger); + } + + // Called once the command ends or is interrupted. + @Override + public void end(boolean interrupted) {} + + // Returns true when the command should end. + @Override + public boolean isFinished() { + return false; + } +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/controllers/LogitechF310.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/controllers/LogitechF310.java new file mode 100644 index 0000000..57ba088 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/controllers/LogitechF310.java @@ -0,0 +1,463 @@ +package frc.robot.controllers; + +import edu.wpi.first.wpilibj.Joystick; + +/** + * This class is used to create an LogitechF310 controller object. + *

+ * This class uses the {@code Joystick} class from the wpilibj library. + *

+ *

+ * This uses a deadband that can be set if needed. This helps control drift. + * This value can be in a range of 0 to 1. The higher the value, the more the + * stick has to move to register. This value is set in the constructor and is + * set alongside the controller ID. As a note: The deadband is only applied + * to the joystick axes. + *

+ * + * @see PS4 + * @see Xbox + * + * @see edu.wpi.first.wpilibj.Joystick + */ +public class LogitechF310 { + + // Button IDs // + + /** + * The axis ID for the left joystick x. + */ + private static final int JOYSTICK_LEFT_X = 0; + + /** + * The axis ID for the left joystick y. + */ + private static final int JOYSTICK_LEFT_Y = 1; + + /** + * The axis ID for the left trigger. + */ + private static final int TRIGGER_LEFT = 2; + + /** + * The axis ID for the right trigger. + */ + private static final int TRIGGER_RIGHT = 3; + + /** + * The axis ID for the right joystick x. + */ + private static final int JOYSTICK_RIGHT_X = 4; + + /** + * The axis ID for the right joystick y. + */ + private static final int JOYSTICK_RIGHT_Y = 5; + + /** + * The button ID for the A button. + */ + private static final int BUTTON_A = 1; + + /** + * The button ID for the B button. + */ + private static final int BUTTON_B = 2; + + /** + * The button ID for the X button. + */ + private static final int BUTTON_X = 3; + + /** + * The button ID for the Y button. + */ + private static final int BUTTON_Y = 4; + + /** + * The button ID for the left bumper. + */ + private static final int BUTTON_LEFT_BUMPER = 5; + + /** + * The button ID for the right bumper. + */ + private static final int BUTTON_RIGHT_BUMPER = 6; + + /** + * The button ID for the start button. + */ + private static final int BUTTON_START = 7; + + /** + * The button ID for the back button. + */ + private static final int BUTTON_BACK = 8; + + /** + * The controller object. + * In this case, a {@code Joystick} object. + * + * @see edu.wpi.first.wpilibj.Joystick + */ + private Joystick controller; + + /** + * The deadband value. + */ + private double deadBand; + + /** + * Constructor for the LogitechF310 class. + *

+ * This constructor is used to create a LogitechF310 object. + * This takes in the controller ID and the deadband value. + *

+ * + * @param id Controller ID (Port) + * @param deadBandValue Deadband value + */ + public LogitechF310(final int id, final double deadBandValue) { + controller = new Joystick(id); + deadBand = deadBandValue; + } + + // Deadband Method // + + /** + * Method for setting the deadband of the controller on the X and Y axes. + *

+ * This sets a threshold the joystick must pass before registering a value. + * This value can be in a range of 0 to 1. The higher the value, + * the more the joystick has to move to register. + *

+ * + * @return Deadbanded value + * + * @param value Value to be deadbanded + */ + private double deadBand(final double value) { + return Math.abs(value) < deadBand ? 0 : value; + } + + // Joystick Methods // + + /** + * Method for returning the X value of the left joystick. + * + * @return X value of the left joystick + * + * @see LogitechF310#getRightX + * @see LogitechF310#getRightY + * @see LogitechF310#getLeftY + */ + public double getLeftX() { + return deadBand(controller.getRawAxis(JOYSTICK_LEFT_X)); + } + + /** + * Method for returning the Y value of the left joystick. + * + * @return Y value of the left joystick + * + * @see LogitechF310#getRightX + * @see LogitechF310#getRightY + * @see LogitechF310#getLeftX + */ + public double getLeftY() { + return deadBand(controller.getRawAxis(JOYSTICK_LEFT_Y)); + } + + /** + * Method for returning the X value of the right joystick. + * + * @return X value of the right joystick + * + * @see LogitechF310#getRightY + * @see LogitechF310#getLeftX + * @see LogitechF310#getLeftY + */ + public double getRightX() { + return deadBand(controller.getRawAxis(JOYSTICK_RIGHT_X)); + } + + /** + * Method for returning the Y value of the right joystick. + * + * @return Y value of the right joystick + * + * @see LogitechF310#getRightX + * @see LogitechF310#getLeftX + * @see LogitechF310#getLeftY + */ + public double getRightY() { + return deadBand(controller.getRawAxis(JOYSTICK_RIGHT_Y)); + } + + // Trigger Methods // + + /** + * Method for returning the value of the left trigger. + * + * @return Value of the left trigger + * + * @see LogitechF310#getRightTrigger + */ + public double getLeftTrigger() { + return deadBand(controller.getRawAxis(TRIGGER_LEFT)); + } + + /** + * Method for returning the value of the right trigger. + * + * @return Value of the right trigger + * + * @see LogitechF310#getLeftTrigger + */ + public double getRightTrigger() { + return deadBand(controller.getRawAxis(TRIGGER_RIGHT)); + } + + // Button Methods // + + /** + * Method for returning the value of the A button. + * + * @return Value of the A button + * + * @see LogitechF310#getBButton + * @see LogitechF310#getXButton + * @see LogitechF310#getYButton + */ + public boolean getAButton() { + return controller.getRawButton(BUTTON_A); + } + + /** + * Method for returning the value of the B button. + * + * @return Value of the B button + * + * @see LogitechF310#getAButton + * @see LogitechF310#getXButton + * @see LogitechF310#getYButton + */ + public boolean getBButton() { + return controller.getRawButton(BUTTON_B); + } + + /** + * Method for returning the value of the X button. + * + * @return Value of the X button + * + * @see LogitechF310#getAButton + * @see LogitechF310#getBButton + * @see LogitechF310#getYButton + */ + public boolean getXButton() { + return controller.getRawButton(BUTTON_X); + } + + /** + * Method for returning the value of the Y button. + * + * @return Value of the Y button + * + * @see LogitechF310#getAButton + * @see LogitechF310#getBButton + * @see LogitechF310#getXButton + */ + public boolean getYButton() { + return controller.getRawButton(BUTTON_Y); + } + + /** + * Method for returning the value of the back button. + * + * @return Value of the back button + * + * @see LogitechF310#getStartButton + */ + public boolean getBackButton() { + return controller.getRawButton(BUTTON_START); + } + + /** + * Method for returning the value of the start button. + * + * @return Value of the start button + * + * @see LogitechF310#getBackButton + */ + public boolean getStartButton() { + return controller.getRawButton(BUTTON_BACK); + } + + /** + * Method for returning the value of the left bumper. + * + * @return Value of the left bumper + * + * @see LogitechF310#getRightBumper + */ + public boolean getLeftBumper() { + return controller.getRawButton(BUTTON_LEFT_BUMPER); + } + + /** + * Method for returning the value of the right bumper. + * + * @return Value of the right bumper + * + * @see LogitechF310#getLeftBumper + */ + public boolean getRightBumper() { + return controller.getRawButton(BUTTON_RIGHT_BUMPER); + } + + // D-Pad Methods // + + public enum DPad { + /** + * Up on the D-Pad. + */ + up, + + /** + * Down on the D-Pad. + */ + down, + + /** + * Right on the D-Pad. + */ + left, + + /** + * Left on the D-Pad. + */ + right, + + /** + * Up-Right on the D-Pad. + */ + upright, + + /** + * Up-Left on the D-Pad. + */ + upleft, + + /** + * Down-Right on the D-Pad. + */ + downright, + + /** + * Down-Left on the D-Pad. + */ + downleft, + + /** + * No direction on the D-Pad. + */ + none + } + + /** + * Upright D-Pad POV value. + */ + private static final int DPAD_UPRIGHT = 45; + + /** + * Right D-Pad POV value. + */ + private static final int DPAD_RIGHT = 90; + + /** + * Downright D-Pad POV value. + */ + private static final int DPAD_DOWNRIGHT = 135; + + /** + * Down POV D-Pad value. + */ + private static final int DPAD_DOWN = 180; + + /** + * Downleft D-Pad POV value. + */ + private static final int DPAD_DOWNLEFT = 225; + + /** + * Left D-Pad POV value. + */ + private static final int DPAD_LEFT = 270; + + /** + * Upleft D-Pad POV value. + */ + private static final int DPAD_UPLEFT = 315; + + /** + * Up D-Pad POV value. + */ + private static final int DPAD_UP = 360; + + /** + * Method for returning the value of the D-Pad. + * + * @return value of the D-Pad + * + * @see LogitechF310.DPad + */ + public DPad getDPad() { + switch (controller.getPOV()) { + case 0: + return DPad.up; + case DPAD_UPRIGHT: + return DPad.upright; + case DPAD_RIGHT: + return DPad.right; + case DPAD_DOWNRIGHT: + return DPad.downright; + case DPAD_DOWN: + return DPad.down; + case DPAD_DOWNLEFT: + return DPad.downleft; + case DPAD_LEFT: + return DPad.left; + case DPAD_UPLEFT: + return DPad.upleft; + case DPAD_UP: + return DPad.up; + default: + return DPad.none; + } + } + + // Rumble Methods // + + // This controller does not have rumble functionality :( + + // General Methods // + + /** + * Method for checking if the controller is connected. + * + * @return true if the controller is connected, false if not + */ + public boolean isConnected() { + return (controller.isConnected()); + } + + /** + * Method for getting the name of the controller. + * + * @return name of the controller + */ + public String getName() { + return controller.getName(); + } +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/controllers/PS4.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/controllers/PS4.java new file mode 100644 index 0000000..398da6c --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/controllers/PS4.java @@ -0,0 +1,498 @@ +package frc.robot.controllers; + +import edu.wpi.first.wpilibj.PS4Controller; +import edu.wpi.first.wpilibj.GenericHID.RumbleType; + +/** + * This class is used to create an PS4 controller object. + *

+ * This class uses the {@code PS4Controller} class from the wpilibj library. + *

+ *

+ * This uses a deadband that can be set if needed. This helps control drift. + * This value can be in a range of 0 to 1. The higher the value, the more the + * stick has to move to register. This value is set in the constructor and is + * set alongside the controller ID. As a note: The deadband is only applied + * to the joystick axes. + *

+ * + * @see LogitechF310 + * @see Xbox + * + * @see edu.wpi.first.wpilibj.PS4Controller + */ +public class PS4 { + + /** + * The controller object. + * In this case, a {@code PS4Controller} object. + * + * @see edu.wpi.first.wpilibj.PS4Controller + */ + private PS4Controller controller; + + /** + * The deadband value. + */ + private double deadBand; + + /** + * Constructor for the PS4 class. + *

+ * This constructor is used to create a LogitechF310 object. + * This takes in the controller ID and the deadband value. + *

+ * + * @param id Controller ID (Port) + * @param deadBandValue Deadband value + */ + public PS4(final int id, final double deadBandValue) { + controller = new PS4Controller(id); + deadBand = deadBandValue; + } + + // Deadband Method // + + // Although this isn't really needed for newer controllers, + // it's still here just in case one might develop drift + + /** + * Method for setting the deadband of the controller on the X and Y axes. + *

+ * This sets a threshold the joystick must pass before registering a value. + * This value can be in a range of 0 to 1. The higher the value, + * the more the joystick has to move to register. + *

+ * + * @return Deadbanded value + * + * @param value Value to be deadbanded + */ + private double deadBand(final double value) { + return Math.abs(value) < deadBand ? 0 : value; + } + + // Joystick Methods // + + /** + * Method for returning the X value of the left joystick. + * + * @return X value of the left joystick + * + * @see PS4#getRightX + * @see PS4#getRightY + * @see PS4#getLeftY + */ + public double getLeftX() { + return deadBand(controller.getLeftX()); + } + + /** + * Method for returning the Y value of the left joystick. + * + * @return Y value of the left joystick + * + * @see PS4#getRightX + * @see PS4#getRightY + * @see PS4#getLeftX + */ + public double getLeftY() { + return deadBand(controller.getLeftY()); + } + + /** + * Method for returning the X value of the right joystick. + * + * @return X value of the right joystick + * + * @see PS4#getLeftX + * @see PS4#getRightY + * @see PS4#getLeftY + */ + public double getRightX() { + return deadBand(controller.getRightX()); + } + + /** + * Method for returning the Y value of the right joystick. + * + * @return Y value of the right joystick + * + * @see PS4#getRightX + * @see PS4#getLeftX + * @see PS4#getLeftY + */ + public double getRightY() { + return deadBand(controller.getRightY()); + } + + // Trigger Methods // + + /** + * Method for returning the value of the left trigger. + * + * @return value of the left trigger + * + * @see PS4#getRightTrigger + */ + public double getLeftTrigger() { + return deadBand(controller.getL2Axis()); + } + + /** + * Method for returning the value of the right trigger. + * + * @return value of the right trigger + * + * @see PS4#getLeftTrigger + */ + public double getRightTrigger() { + return deadBand(controller.getR2Axis()); + } + + // Button Methods // + + /** + * Method for returning the value of the X button. + * + * @return value of the X button + * + * @see PS4#getSquareButton + * @see PS4#getCircleButton + * @see PS4#getTriangleButton + * @see PS4#getShareButton + * @see PS4#getOptionsButton + * @see PS4#getPlayStationButton + * @see PS4#getTouchpadButton + */ + public boolean getXButton() { + return controller.getCrossButton(); + } + + /** + * Method for returning the value of the Square button. + * + * @return value of the Square button + * + * @see PS4#getXButton + * @see PS4#getCircleButton + * @see PS4#getTriangleButton + * @see PS4#getShareButton + * @see PS4#getOptionsButton + * @see PS4#getPlayStationButton + * @see PS4#getTouchpadButton + */ + public boolean getSquareButton() { + return controller.getSquareButton(); + } + + /** + * Method for returning the value of the Circle button. + * + * @return value of the Circle button + * + * @see PS4#getXButton + * @see PS4#getSquareButton + * @see PS4#getTriangleButton + * @see PS4#getShareButton + * @see PS4#getOptionsButton + * @see PS4#getPlayStationButton + * @see PS4#getTouchpadButton + */ + public boolean getCircleButton() { + return controller.getCircleButton(); + } + + /** + * Method for returning the value of the Triangle button. + * + * @return value of the Triangle button + * + * @see PS4#getXButton + * @see PS4#getSquareButton + * @see PS4#getCircleButton + * @see PS4#getShareButton + * @see PS4#getOptionsButton + * @see PS4#getPlayStationButton + * @see PS4#getTouchpadButton + */ + public boolean getTriangleButton() { + return controller.getTriangleButton(); + } + + /** + * Method for returning the value of the Share button. + * + * @return value of the Share button + * + * @see PS4#getXButton + * @see PS4#getSquareButton + * @see PS4#getCircleButton + * @see PS4#getTriangleButton + * @see PS4#getOptionsButton + * @see PS4#getPlayStationButton + * @see PS4#getTouchpadButton + */ + public boolean getShareButton() { + return controller.getShareButton(); + } + + /** + * Method for returning the value of the Options button. + * + * @return value of the Options button + * + * @see PS4#getXButton + * @see PS4#getSquareButton + * @see PS4#getCircleButton + * @see PS4#getTriangleButton + * @see PS4#getShareButton + * @see PS4#getPlayStationButton + * @see PS4#getTouchpadButton + */ + public boolean getOptionsButton() { + return controller.getOptionsButton(); + } + + /** + * Method for returning the value of the PlayStation button. + * + * @return value of the PlayStation button + * + * @see PS4#getXButton + * @see PS4#getSquareButton + * @see PS4#getCircleButton + * @see PS4#getTriangleButton + * @see PS4#getShareButton + * @see PS4#getOptionsButton + * @see PS4#getTouchpadButton + */ + public boolean getPlayStationButton() { + return controller.getPSButton(); + } + + /** + * Method for returning the value of the left bumper. + * + * @return value of the left bumper + * + * @see PS4#getRightBumper + */ + public boolean getLeftBumper() { + return controller.getL1Button(); + } + + /** + * Method for returning the value of the right bumper. + * + * @return value of the right bumper + * + * @see PS4#getLeftBumper + */ + public boolean getRightBumper() { + return controller.getR1Button(); + } + + /** + * Method for returning the value of the left joystick button. + * + * @return value of the left joystick button + * + * @see PS4#getRightJoystickButton + */ + public boolean getLeftJoystickButton() { + return controller.getL3Button(); + } + + /** + * Method for returning the value of the right joystick button. + * + * @return value of the right joystick button + * + * @see PS4#getLeftJoystickButton + */ + public boolean getRightJoystickButton() { + return controller.getR3Button(); + } + + // Touchpad Methods // + + /** + * Method for returning the value of the Touchpad button. + * + * @return value of the Touchpad button + * + * @see PS4#getXButton + * @see PS4#getSquareButton + * @see PS4#getCircleButton + * @see PS4#getTriangleButton + * @see PS4#getShareButton + * @see PS4#getOptionsButton + * @see PS4#getPlayStationButton + */ + public boolean getTouchpadButton() { + return controller.getTouchpad(); + } + + // There is a 'touchpad' that uses an event loop + // but for the purpose of this class, it is not needed + // It might be added in a future version if there becomes a need for it + // If you have a need for it or have added it yourself, + // Submit a pull request or submit an issue on the GitHub repository + // https://github.com/J-The-Fox/FRC-Team-5098 + + // D-Pad Methods // + + public enum DPad { + /** + * Up on the D-Pad. + */ + up, + + /** + * Down on the D-Pad. + */ + down, + + /** + * Right on the D-Pad. + */ + left, + + /** + * Left on the D-Pad. + */ + right, + + /** + * Up-Right on the D-Pad. + */ + upright, + + /** + * Up-Left on the D-Pad. + */ + upleft, + + /** + * Down-Right on the D-Pad. + */ + downright, + + /** + * Down-Left on the D-Pad. + */ + downleft, + + /** + * No direction on the D-Pad. + */ + none + } + + /** + * Upright D-Pad POV value. + */ + private static final int DPAD_UPRIGHT = 45; + + /** + * Right D-Pad POV value. + */ + private static final int DPAD_RIGHT = 90; + + /** + * Downright D-Pad POV value. + */ + private static final int DPAD_DOWNRIGHT = 135; + + /** + * Down POV D-Pad value. + */ + private static final int DPAD_DOWN = 180; + + /** + * Downleft D-Pad POV value. + */ + private static final int DPAD_DOWNLEFT = 225; + + /** + * Left D-Pad POV value. + */ + private static final int DPAD_LEFT = 270; + + /** + * Upleft D-Pad POV value. + */ + private static final int DPAD_UPLEFT = 315; + + /** + * Up D-Pad POV value. + */ + private static final int DPAD_UP = 360; + + /** + * Method for returning the value of the D-Pad. + * + * @return value of the D-Pad + * + * @see PS4.DPad + */ + public DPad getDPad() { + switch (controller.getPOV()) { + case 0: + return DPad.up; + case DPAD_UPRIGHT: + return DPad.upright; + case DPAD_RIGHT: + return DPad.right; + case DPAD_DOWNRIGHT: + return DPad.downright; + case DPAD_DOWN: + return DPad.down; + case DPAD_DOWNLEFT: + return DPad.downleft; + case DPAD_LEFT: + return DPad.left; + case DPAD_UPLEFT: + return DPad.upleft; + case DPAD_UP: + return DPad.up; + default: + return DPad.none; + } + } + + // Rumble Methods // + + /** + * Method for setting the rumble of the controller. + * + * @param type type of rumble to set + * @param value value to set the rumble to + * + * @see edu.wpi.first.wpilibj.GenericHID.RumbleType + */ + public void setRumble(final RumbleType type, final double value) { + controller.setRumble(type, value); + } + + // General Methods // + + /** + * Method for checking if the controller is connected. + * + * @return true if the controller is connected, false if not + */ + public boolean isConnected() { + return (controller.isConnected()); + } + + /** + * Method for getting the name of the controller. + * + * @return name of the controller + */ + public String getName() { + return controller.getName(); + } +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/controllers/Xbox.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/controllers/Xbox.java new file mode 100644 index 0000000..421866a --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/controllers/Xbox.java @@ -0,0 +1,425 @@ +package frc.robot.controllers; + +import edu.wpi.first.wpilibj.XboxController; +import edu.wpi.first.wpilibj.GenericHID.RumbleType; + +/** + * This class is used to create an Xbox controller object. + *

+ * This class uses the {@code XboxController} class from the wpilibj library. + *

+ *

+ * This uses a deadband that can be set if needed. This helps control drift. + * This value can be in a range of 0 to 1. The higher the value, the more the + * stick has to move to register. This value is set in the constructor and is + * set alongside the controller ID. As a note: The deadband is only applied + * to the joystick axes. + *

+ * + * @see LogitechF310 + * @see PS4 + * + * @see edu.wpi.first.wpilibj.XboxController + */ +public class Xbox { + + /** + * The controller object. + * In this case, a {@code XboxController} object. + */ + private XboxController controller; + + /** + * The deadband value. + */ + private double deadBand; + + /** + * Constructor for the Xbox class. + *

+ * This constructor is used to create a LogitechF310 object. + * This takes in the controller ID and the deadband value. + *

+ * + * @param id Controller ID (Port) + * @param deadBandValue Deadband value + */ + public Xbox(final int id, final double deadBandValue) { + controller = new XboxController(id); + deadBand = deadBandValue; + } + + // Deadband Method // + + // Although this isn't really needed for newer controllers, + // it's still here just in case one might develop drift + + /** + * Method for setting the deadband of the controller on the X and Y axes. + *

+ * This sets a threshold the joystick must pass before registering a value. + * This value can be in a range of 0 to 1. The higher the value, + * the more the joystick has to move to register. + *

+ * + * @return Deadbanded value + * + * @param value Value to be deadbanded + */ + private double deadBand(final double value) { + return Math.abs(value) < deadBand ? 0 : value; + } + + // Joystick Methods // + + /** + * Method for returning the X value of the left joystick. + * + * @return X value of the left joystick + * + * @see Xbox#getRightX + * @see Xbox#getRightY + * @see Xbox#getLeftY + */ + public double getLeftX() { + return deadBand(controller.getLeftX()); + } + + /** + * Method for returning the Y value of the left joystick. + * + * @return Y value of the left joystick + * + * @see Xbox#getRightX + * @see Xbox#getRightY + * @see Xbox#getLeftX + */ + public double getLeftY() { + return deadBand(controller.getLeftY()); + } + + /** + * Method for returning the X value of the right joystick. + * + * @return X value of the right joystick + * + * @see Xbox#getRightY + * @see Xbox#getLeftX + * @see Xbox#getLeftY + */ + public double getRightX() { + return deadBand(controller.getRightX()); + } + + /** + * Method for returning the Y value of the right joystick. + * + * @return Y value of the right joystick + * + * @see Xbox#getRightX + * @see Xbox#getLeftX + * @see Xbox#getLeftY + */ + public double getRightY() { + return deadBand(controller.getRightY()); + } + + // Trigger Methods // + + /** + * Method for returning the value of the left trigger. + * + * @return value of the left trigger + * + * @see Xbox#getRightTrigger + */ + public double getLeftTrigger() { + return controller.getLeftTriggerAxis(); + } + + /** + * Method for returning the value of the right trigger. + * + * @return value of the right trigger + * + * @see Xbox#getLeftTrigger + */ + public double getRightTrigger() { + return controller.getRightTriggerAxis(); + } + + // Button Methods // + + /** + * Method for returning the value of the A button. + * + * @return value of the A button + * + * @see Xbox#getBButton + * @see Xbox#getXButton + * @see Xbox#getYButton + */ + public boolean getAButton() { + return controller.getAButton(); + } + + /** + * Method for returning the value of the B button. + * + * @return value of the B button + * + * @see Xbox#getAButton + * @see Xbox#getXButton + * @see Xbox#getYButton + */ + public boolean getBButton() { + return controller.getBButton(); + } + + /** + * Method for returning the value of the X button. + * + * @return value of the X button + * + * @see Xbox#getAButton + * @see Xbox#getBButton + * @see Xbox#getYButton + */ + public boolean getXButton() { + return controller.getXButton(); + } + + /** + * Method for returning the value of the Y button. + * + * @return value of the Y button + * + * @see Xbox#getAButton + * @see Xbox#getBButton + * @see Xbox#getXButton + */ + public boolean getYButton() { + return controller.getYButton(); + } + + /** + * Method for returning the value of the start button. + * + * @return value of the start button + * + * @see Xbox#getBackButton + */ + public boolean getStartButton() { + return controller.getStartButton(); + } + + /** + * Method for returning the value of the back button. + * + * @return value of the back button + * + * @see Xbox#getStartButton + */ + public boolean getBackButton() { + return controller.getBackButton(); + } + + /** + * Method for returning the value of the left bumper. + * + * @return value of the left bumper + * + * @see Xbox#getRightBumper + */ + public boolean getLeftBumper() { + return controller.getLeftBumper(); + } + + /** + * Method for returning the value of the right bumper. + * + * @return value of the right bumper + * + * @see Xbox#getLeftBumper + */ + public boolean getRightBumper() { + return controller.getRightBumper(); + } + + /** + * Method for returning the value of the left stick button. + * + * @return value of the left stick button + * + * @see Xbox#getRightStickButton + */ + public boolean getLeftStickButton() { + return controller.getLeftStickButton(); + } + + /** + * Method for returning the value of the right stick button. + * + * @return value of the right stick button + * + * @see Xbox#getLeftStickButton + */ + public boolean getRightStickButton() { + return controller.getRightStickButton(); + } + + // D-Pad Methods // + + public enum DPad { + /** + * Up on the D-Pad. + */ + up, + + /** + * Down on the D-Pad. + */ + down, + + /** + * Right on the D-Pad. + */ + left, + + /** + * Left on the D-Pad. + */ + right, + + /** + * Up-Right on the D-Pad. + */ + upright, + + /** + * Up-Left on the D-Pad. + */ + upleft, + + /** + * Down-Right on the D-Pad. + */ + downright, + + /** + * Down-Left on the D-Pad. + */ + downleft, + + /** + * No direction on the D-Pad. + */ + none + } + + /** + * Upright D-Pad POV value. + */ + private static final int DPAD_UPRIGHT = 45; + + /** + * Right D-Pad POV value. + */ + private static final int DPAD_RIGHT = 90; + + /** + * Downright D-Pad POV value. + */ + private static final int DPAD_DOWNRIGHT = 135; + + /** + * Down POV D-Pad value. + */ + private static final int DPAD_DOWN = 180; + + /** + * Downleft D-Pad POV value. + */ + private static final int DPAD_DOWNLEFT = 225; + + /** + * Left D-Pad POV value. + */ + private static final int DPAD_LEFT = 270; + + /** + * Upleft D-Pad POV value. + */ + private static final int DPAD_UPLEFT = 315; + + /** + * Up D-Pad POV value. + */ + private static final int DPAD_UP = 360; + + /** + * Method for returning the value of the D-Pad. + * + * @return value of the D-Pad + * + * @see Xbox.DPad + */ + public DPad getDPad() { + switch (controller.getPOV()) { + case 0: + return DPad.up; + case DPAD_UPRIGHT: + return DPad.upright; + case DPAD_RIGHT: + return DPad.right; + case DPAD_DOWNRIGHT: + return DPad.downright; + case DPAD_DOWN: + return DPad.down; + case DPAD_DOWNLEFT: + return DPad.downleft; + case DPAD_LEFT: + return DPad.left; + case DPAD_UPLEFT: + return DPad.upleft; + case DPAD_UP: + return DPad.up; + default: + return DPad.none; + } + } + + // Rumble Methods // + + /** + * Method for setting the rumble of the controller. + * + * @param type type of rumble to set + * @param value value to set the rumble to + * + * @see edu.wpi.first.wpilibj.GenericHID.RumbleType + */ + public void setRumble(final RumbleType type, final double value) { + controller.setRumble(type, value); + } + + // General Methods // + + /** + * Method for checking if the controller is connected. + * + * @return true if the controller is connected, false if not + */ + public boolean isConnected() { + return (controller.isConnected()); + } + + /** + * Method for getting the name of the controller. + * + * @return name of the controller + */ + public String getName() { + return controller.getName(); + } +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/controllers/package-info.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/controllers/package-info.java new file mode 100644 index 0000000..7c768d9 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/controllers/package-info.java @@ -0,0 +1,7 @@ +/** + * Holds controller classes + *

+ * This can be used to hold both custom and pre-made controller classes. + *

+ */ +package frc.robot.controllers; diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/subsystems/DriveSubsystem.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/subsystems/DriveSubsystem.java new file mode 100644 index 0000000..6877d47 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/subsystems/DriveSubsystem.java @@ -0,0 +1,47 @@ +package frc.robot.subsystems; + +import edu.wpi.first.wpilibj2.command.SubsystemBase; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; +import edu.wpi.first.wpilibj2.command.Command; +import com.ctre.phoenix.motorcontrol.can.TalonSRX; +import com.ctre.phoenix.motorcontrol.ControlMode; + +public class DriveSubsystem extends SubsystemBase { + + // Motors + private final TalonSRX FLMotor; + private final TalonSRX FRMotor; + private final TalonSRX BLMotor; + private final TalonSRX BRMotor; + + public DriveSubsystem(int FLId, int FRId, int BLId, int BRId) { + FLMotor = new TalonSRX(FLId); + FRMotor = new TalonSRX(FRId); + BLMotor = new TalonSRX(BLId); + BRMotor = new TalonSRX(BRId); + } + + public Command setMotorVoltageCommand(double leftTrigger, double rightTrigger, double rightXAxis) { + return runOnce(() -> { + // System.out.println("Command Ran"); + setMotorVoltage(leftTrigger, rightTrigger, rightXAxis); + }); + } + + public void setMotorVoltage(double leftTrigger, double rightTrigger, double rightXAxis) { + // System.out.println("method ran"); + FLMotor.set(ControlMode.PercentOutput, rightTrigger -leftTrigger + rightXAxis); + FRMotor.set(ControlMode.PercentOutput, -rightTrigger + leftTrigger -rightXAxis); + BLMotor.set(ControlMode.PercentOutput, rightTrigger -leftTrigger + rightXAxis); + BRMotor.set(ControlMode.PercentOutput, -rightTrigger + leftTrigger -rightXAxis); + + // FLMotor.set(ControlMode.PercentOutput, 0.5); + // BLMotor.set(ControlMode.PercentOutput, 0.5); + + SmartDashboard.putNumber("Left Trigger", leftTrigger); + SmartDashboard.putNumber("Right Trigger", rightTrigger); + SmartDashboard.putNumber("Stick", rightXAxis); + + } + +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/subsystems/ExampleSubsystem.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/subsystems/ExampleSubsystem.java new file mode 100644 index 0000000..53776e3 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/src/main/java/frc/robot/subsystems/ExampleSubsystem.java @@ -0,0 +1,70 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot.subsystems; + +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.SubsystemBase; +import com.ctre.phoenix.motorcontrol.can.TalonSRX; +import com.ctre.phoenix.motorcontrol.ControlMode; + +public class ExampleSubsystem extends SubsystemBase { + + private final TalonSRX testMotor; + /** Creates a new ExampleSubsystem. */ + public ExampleSubsystem(int testId) { + testMotor = new TalonSRX(testId); + } + + /** + * Example command factory method. + * + * @return a command + */ + public Command exampleMethodCommand() { + // Inline construction of command goes here. + // Subsystem::RunOnce implicitly requires `this` subsystem. + return runOnce(() + -> { + /* one-time action goes here */ + }); + } + + public Command setMotorVoltageCommand(double voltage) { + return runOnce(() + -> { + setMotorVoltage(voltage); + }); + } + + /** + * An example method querying a boolean state of the subsystem (for example, a + * digital sensor). + * + * @return value of some boolean subsystem state, such as a digital sensor. + */ + public boolean exampleCondition() { + // Query some boolean state, such as a digital sensor. + int x = 3; + if (x != 1) { + return false; + } + return true; + + } + + public void setMotorVoltage(double voltage) { + testMotor.set(ControlMode.PercentOutput, voltage); + } + + @Override + public void periodic() { + // This method will be called once per scheduler run + } + + @Override + public void simulationPeriodic() { + // This method will be called once per scheduler run during simulation + } +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/vendordeps/AdvantageKit.json b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/vendordeps/AdvantageKit.json new file mode 100644 index 0000000..1fa7c03 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/vendordeps/AdvantageKit.json @@ -0,0 +1,34 @@ +{ + "fileName": "AdvantageKit.json", + "name": "AdvantageKit", + "version": "4.0.0", + "uuid": "d820cc26-74e3-11ec-90d6-0242ac120003", + "frcYear": "2025", + "mavenUrls": [ + "https://frcmaven.wpi.edu/artifactory/littletonrobotics-mvn-release/" + ], + "jsonUrl": "https://github.com/Mechanical-Advantage/AdvantageKit/releases/latest/download/AdvantageKit.json", + "javaDependencies": [ + { + "groupId": "org.littletonrobotics.akit", + "artifactId": "akit-java", + "version": "4.0.0" + } + ], + "jniDependencies": [ + { + "groupId": "org.littletonrobotics.akit", + "artifactId": "akit-wpilibio", + "version": "4.0.0", + "skipInvalidPlatforms": false, + "isJar": false, + "validPlatforms": [ + "linuxathena", + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ] + } + ], + "cppDependencies": [] +} \ No newline at end of file diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/vendordeps/PathplannerLib-2025.2.1.json b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/vendordeps/PathplannerLib-2025.2.1.json new file mode 100644 index 0000000..71e25f3 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/vendordeps/PathplannerLib-2025.2.1.json @@ -0,0 +1,38 @@ +{ + "fileName": "PathplannerLib-2025.2.1.json", + "name": "PathplannerLib", + "version": "2025.2.1", + "uuid": "1b42324f-17c6-4875-8e77-1c312bc8c786", + "frcYear": "2025", + "mavenUrls": [ + "https://3015rangerrobotics.github.io/pathplannerlib/repo" + ], + "jsonUrl": "https://3015rangerrobotics.github.io/pathplannerlib/PathplannerLib.json", + "javaDependencies": [ + { + "groupId": "com.pathplanner.lib", + "artifactId": "PathplannerLib-java", + "version": "2025.2.1" + } + ], + "jniDependencies": [], + "cppDependencies": [ + { + "groupId": "com.pathplanner.lib", + "artifactId": "PathplannerLib-cpp", + "version": "2025.2.1", + "libName": "PathplannerLib", + "headerClassifier": "headers", + "sharedLibrary": false, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal", + "linuxathena", + "linuxarm32", + "linuxarm64" + ] + } + ] +} \ No newline at end of file diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/vendordeps/Phoenix5-replay-5.35.1.json b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/vendordeps/Phoenix5-replay-5.35.1.json new file mode 100644 index 0000000..bdf2f44 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/vendordeps/Phoenix5-replay-5.35.1.json @@ -0,0 +1,221 @@ +{ + "fileName": "Phoenix5-replay-5.35.1.json", + "name": "CTRE-Phoenix (v5)", + "version": "5.35.1", + "frcYear": "2025", + "uuid": "fbc886a4-2cec-40c0-9835-71086a8cc3df", + "mavenUrls": [ + "https://maven.ctr-electronics.com/release/" + ], + "jsonUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix/Phoenix5-replay-frc2025-latest.json", + "requires": [ + { + "uuid": "e7900d8d-826f-4dca-a1ff-182f658e98af", + "errorMessage": "Phoenix 5 requires low-level libraries from Phoenix 6. Please add the Phoenix 6 vendordep before adding Phoenix 5.", + "offlineFileName": "Phoenix6-replay-frc2025-latest.json", + "onlineUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix6/latest/Phoenix6-replay-frc2025-latest.json" + } + ], + "conflictsWith": [ + { + "uuid": "e995de00-2c64-4df5-8831-c1441420ff19", + "errorMessage": "Users must use the regular Phoenix 5 vendordep when using the regular Phoenix 6 vendordep.", + "offlineFileName": "Phoenix6-frc2025-latest.json" + }, + { + "uuid": "ab676553-b602-441f-a38d-f1296eff6537", + "errorMessage": "Users cannot have both the replay and regular Phoenix 5 vendordeps in their robot program.", + "offlineFileName": "Phoenix5-frc2025-latest.json" + } + ], + "javaDependencies": [ + { + "groupId": "com.ctre.phoenix", + "artifactId": "api-java", + "version": "5.35.1" + }, + { + "groupId": "com.ctre.phoenix", + "artifactId": "wpiapi-java", + "version": "5.35.1" + } + ], + "jniDependencies": [ + { + "groupId": "com.ctre.phoenix", + "artifactId": "cci", + "version": "5.35.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix.replay", + "artifactId": "cci-replay", + "version": "5.35.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "cci-sim", + "version": "5.35.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + } + ], + "cppDependencies": [ + { + "groupId": "com.ctre.phoenix", + "artifactId": "wpiapi-cpp", + "version": "5.35.1", + "libName": "CTRE_Phoenix_WPI", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix", + "artifactId": "api-cpp", + "version": "5.35.1", + "libName": "CTRE_Phoenix", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix", + "artifactId": "cci", + "version": "5.35.1", + "libName": "CTRE_PhoenixCCI", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix.replay", + "artifactId": "wpiapi-cpp-replay", + "version": "5.35.1", + "libName": "CTRE_Phoenix_WPIReplay", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix.replay", + "artifactId": "api-cpp-replay", + "version": "5.35.1", + "libName": "CTRE_PhoenixReplay", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix.replay", + "artifactId": "cci-replay", + "version": "5.35.1", + "libName": "CTRE_PhoenixCCIReplay", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "wpiapi-cpp-sim", + "version": "5.35.1", + "libName": "CTRE_Phoenix_WPISim", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "api-cpp-sim", + "version": "5.35.1", + "libName": "CTRE_PhoenixSim", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "cci-sim", + "version": "5.35.1", + "libName": "CTRE_PhoenixCCISim", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + } + ] +} \ No newline at end of file diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/vendordeps/Phoenix6-replay-25.2.0.json b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/vendordeps/Phoenix6-replay-25.2.0.json new file mode 100644 index 0000000..52725fb --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/vendordeps/Phoenix6-replay-25.2.0.json @@ -0,0 +1,467 @@ +{ + "fileName": "Phoenix6-replay-25.2.0.json", + "name": "CTRE-Phoenix (v6) Replay", + "version": "25.2.0", + "frcYear": "2025", + "uuid": "e7900d8d-826f-4dca-a1ff-182f658e98af", + "mavenUrls": [ + "https://maven.ctr-electronics.com/release/" + ], + "jsonUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix6/latest/Phoenix6-replay-frc2025-latest.json", + "conflictsWith": [ + { + "uuid": "e995de00-2c64-4df5-8831-c1441420ff19", + "errorMessage": "Users can not have both the replay and regular Phoenix 6 vendordeps in their robot program.", + "offlineFileName": "Phoenix6-frc2025-latest.json" + } + ], + "javaDependencies": [ + { + "groupId": "com.ctre.phoenix6", + "artifactId": "wpiapi-java", + "version": "25.2.0" + } + ], + "jniDependencies": [ + { + "groupId": "com.ctre.phoenix6", + "artifactId": "api-cpp", + "version": "25.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6", + "artifactId": "tools", + "version": "25.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6.replay", + "artifactId": "api-cpp-replay", + "version": "25.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6.replay", + "artifactId": "tools-replay", + "version": "25.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "api-cpp-sim", + "version": "25.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "tools-sim", + "version": "25.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simTalonSRX", + "version": "25.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simVictorSPX", + "version": "25.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simPigeonIMU", + "version": "25.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simCANCoder", + "version": "25.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProTalonFX", + "version": "25.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProTalonFXS", + "version": "25.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANcoder", + "version": "25.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProPigeon2", + "version": "25.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANrange", + "version": "25.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + } + ], + "cppDependencies": [ + { + "groupId": "com.ctre.phoenix6", + "artifactId": "wpiapi-cpp", + "version": "25.2.0", + "libName": "CTRE_Phoenix6_WPI", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6", + "artifactId": "tools", + "version": "25.2.0", + "libName": "CTRE_PhoenixTools", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6.replay", + "artifactId": "wpiapi-cpp-replay", + "version": "25.2.0", + "libName": "CTRE_Phoenix6_WPIReplay", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6.replay", + "artifactId": "tools-replay", + "version": "25.2.0", + "libName": "CTRE_PhoenixTools_Replay", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "wpiapi-cpp-sim", + "version": "25.2.0", + "libName": "CTRE_Phoenix6_WPISim", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "tools-sim", + "version": "25.2.0", + "libName": "CTRE_PhoenixTools_Sim", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simTalonSRX", + "version": "25.2.0", + "libName": "CTRE_SimTalonSRX", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simVictorSPX", + "version": "25.2.0", + "libName": "CTRE_SimVictorSPX", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simPigeonIMU", + "version": "25.2.0", + "libName": "CTRE_SimPigeonIMU", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simCANCoder", + "version": "25.2.0", + "libName": "CTRE_SimCANCoder", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProTalonFX", + "version": "25.2.0", + "libName": "CTRE_SimProTalonFX", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProTalonFXS", + "version": "25.2.0", + "libName": "CTRE_SimProTalonFXS", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANcoder", + "version": "25.2.0", + "libName": "CTRE_SimProCANcoder", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProPigeon2", + "version": "25.2.0", + "libName": "CTRE_SimProPigeon2", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANrange", + "version": "25.2.0", + "libName": "CTRE_SimProCANrange", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + } + ] +} \ No newline at end of file diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/vendordeps/WPILibNewCommands.json b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/vendordeps/WPILibNewCommands.json new file mode 100644 index 0000000..3718e0a --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test-Imported/vendordeps/WPILibNewCommands.json @@ -0,0 +1,38 @@ +{ + "fileName": "WPILibNewCommands.json", + "name": "WPILib-New-Commands", + "version": "1.0.0", + "uuid": "111e20f7-815e-48f8-9dd6-e675ce75b266", + "frcYear": "2025", + "mavenUrls": [], + "jsonUrl": "", + "javaDependencies": [ + { + "groupId": "edu.wpi.first.wpilibNewCommands", + "artifactId": "wpilibNewCommands-java", + "version": "wpilib" + } + ], + "jniDependencies": [], + "cppDependencies": [ + { + "groupId": "edu.wpi.first.wpilibNewCommands", + "artifactId": "wpilibNewCommands-cpp", + "version": "wpilib", + "libName": "wpilibNewCommands", + "headerClassifier": "headers", + "sourcesClassifier": "sources", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena", + "linuxarm32", + "linuxarm64", + "windowsx86-64", + "windowsx86", + "linuxx86-64", + "osxuniversal" + ] + } + ] +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/.wpilib/wpilib_preferences.json b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/.wpilib/wpilib_preferences.json new file mode 100644 index 0000000..a5ebb07 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/.wpilib/wpilib_preferences.json @@ -0,0 +1,6 @@ +{ + "enableCppIntellisense": false, + "currentLanguage": "java", + "projectYear": "2024", + "teamNumber": 5098 +} \ No newline at end of file diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/WPILib-License.md b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/WPILib-License.md new file mode 100644 index 0000000..e7cd597 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/WPILib-License.md @@ -0,0 +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. diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/build.gradle b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/build.gradle new file mode 100644 index 0000000..1e8da00 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/build.gradle @@ -0,0 +1,101 @@ +plugins { + id "java" + id "edu.wpi.first.GradleRIO" version "2024.2.1" +} + +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 = false + +// Defining my dependencies. In this case, WPILib (+ friends), and vendor libraries. +// Also defines JUnit 5. +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' +} + +test { + useJUnitPlatform() + systemProperty 'junit.jupiter.extensions.autodetection.enabled', 'true' +} + +// Simulation configuration (e.g. environment variables). +wpi.sim.addGui().defaultEnabled = true +wpi.sim.addDriverstation() + +// Setting up my Jar File. In this case, adding all libraries into the main jar ('fat 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' +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/gradle/wrapper/gradle-wrapper.properties b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..7015f6b --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=permwrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=permwrapper/dists diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/gradlew b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/gradlew new file mode 100644 index 0000000..1aa94a4 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/gradlew.bat b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/gradlew.bat new file mode 100644 index 0000000..6689b85 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/settings.gradle b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/settings.gradle new file mode 100644 index 0000000..3e30f84 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/settings.gradle @@ -0,0 +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"); diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/deploy/example.txt b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/deploy/example.txt new file mode 100644 index 0000000..bb82515 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/deploy/example.txt @@ -0,0 +1,3 @@ +Files placed in this directory will be deployed to the RoboRIO into the +'deploy' directory in the home folder. Use the 'Filesystem.getDeployDirectory' wpilib function +to get a proper path relative to the deploy directory. \ No newline at end of file diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/Constants.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/Constants.java new file mode 100644 index 0000000..c50ba05 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/Constants.java @@ -0,0 +1,19 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot; + +/** + * 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 class OperatorConstants { + public static final int kDriverControllerPort = 0; + } +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/Main.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/Main.java new file mode 100644 index 0000000..8776e5d --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/Main.java @@ -0,0 +1,25 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package 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/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/Robot.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/Robot.java new file mode 100644 index 0000000..687a0a0 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/Robot.java @@ -0,0 +1,103 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot; + +import edu.wpi.first.wpilibj.TimedRobot; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.CommandScheduler; + +/** + * The VM is configured to automatically run this class, and to call the functions corresponding to + * each mode, as described in the TimedRobot documentation. If you change the name of this class or + * the package after creating this project, you must also update the build.gradle file in the + * project. + */ +public class Robot extends TimedRobot { + private Command m_autonomousCommand; + + private RobotContainer m_robotContainer; + + /** + * This function is run when the robot is first started up and should be used for any + * initialization code. + */ + @Override + public void robotInit() { + // Instantiate our RobotContainer. This will perform all our button bindings, and put our + // autonomous chooser on the dashboard. + m_robotContainer = new RobotContainer(); + } + + /** + * This function is called every 20 ms, no matter the mode. Use this for items like diagnostics + * that you want ran during disabled, autonomous, teleoperated and test. + * + *

This runs after the mode specific periodic functions, but before LiveWindow and + * SmartDashboard integrated updating. + */ + @Override + public void robotPeriodic() { + // Runs the Scheduler. This is responsible for polling buttons, adding newly-scheduled + // commands, running already-scheduled commands, removing finished or interrupted commands, + // and running subsystem periodic() methods. This must be called from the robot's periodic + // block in order for anything in the Command-based framework to work. + CommandScheduler.getInstance().run(); + } + + /** This function is called once each time the robot enters Disabled mode. */ + @Override + public void disabledInit() {} + + @Override + public void disabledPeriodic() {} + + /** This autonomous runs the autonomous command selected by your {@link RobotContainer} class. */ + @Override + public void autonomousInit() { + m_autonomousCommand = m_robotContainer.getAutonomousCommand(); + + // schedule the autonomous command (example) + if (m_autonomousCommand != null) { + m_autonomousCommand.schedule(); + } + } + + /** This function is called periodically during autonomous. */ + @Override + public void autonomousPeriodic() {} + + @Override + public void teleopInit() { + // This makes sure that the autonomous stops running when + // teleop starts running. If you want the autonomous to + // continue until interrupted by another command, remove + // this line or comment it out. + if (m_autonomousCommand != null) { + m_autonomousCommand.cancel(); + } + } + + /** This function is called periodically during operator control. */ + @Override + public void teleopPeriodic() {} + + @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/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/RobotContainer.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/RobotContainer.java new file mode 100644 index 0000000..a33249e --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/RobotContainer.java @@ -0,0 +1,63 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot; + +import frc.robot.Constants.OperatorConstants; +import frc.robot.commands.Autos; +import frc.robot.commands.ExampleCommand; +import frc.robot.subsystems.ExampleSubsystem; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.button.CommandXboxController; +import edu.wpi.first.wpilibj2.command.button.Trigger; + +/** + * This class is where the bulk of the robot should be declared. Since Command-based is a + * "declarative" paradigm, very little robot logic should actually be handled in the {@link Robot} + * periodic methods (other than the scheduler calls). Instead, the structure of the robot (including + * subsystems, commands, and trigger mappings) should be declared here. + */ +public class RobotContainer { + // The robot's subsystems and commands are defined here... + private final ExampleSubsystem m_exampleSubsystem = new ExampleSubsystem(); + + // Replace with CommandPS4Controller or CommandJoystick if needed + private final CommandXboxController m_driverController = + new CommandXboxController(OperatorConstants.kDriverControllerPort); + + /** The container for the robot. Contains subsystems, OI devices, and commands. */ + public RobotContainer() { + // Configure the trigger bindings + configureBindings(); + } + + /** + * Use this method to define your trigger->command mappings. Triggers can be created via the + * {@link Trigger#Trigger(java.util.function.BooleanSupplier)} constructor with an arbitrary + * predicate, or via the named factories in {@link + * edu.wpi.first.wpilibj2.command.button.CommandGenericHID}'s subclasses for {@link + * CommandXboxController Xbox}/{@link edu.wpi.first.wpilibj2.command.button.CommandPS4Controller + * PS4} controllers or {@link edu.wpi.first.wpilibj2.command.button.CommandJoystick Flight + * joysticks}. + */ + private void configureBindings() { + // Schedule `ExampleCommand` when `exampleCondition` changes to `true` + new Trigger(m_exampleSubsystem::exampleCondition) + .onTrue(new ExampleCommand(m_exampleSubsystem)); + + // Schedule `exampleMethodCommand` when the Xbox controller's B button is pressed, + // cancelling on release. + m_driverController.b().whileTrue(m_exampleSubsystem.exampleMethodCommand()); + } + + /** + * Use this to pass the autonomous command to the main {@link Robot} class. + * + * @return the command to run in autonomous + */ + public Command getAutonomousCommand() { + // An example command will be run in autonomous + return Autos.exampleAuto(m_exampleSubsystem); + } +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/commands/Autos.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/commands/Autos.java new file mode 100644 index 0000000..107aad7 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/commands/Autos.java @@ -0,0 +1,20 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot.commands; + +import frc.robot.subsystems.ExampleSubsystem; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.Commands; + +public final class Autos { + /** Example static factory for an autonomous command. */ + public static Command exampleAuto(ExampleSubsystem subsystem) { + return Commands.sequence(subsystem.exampleMethodCommand(), new ExampleCommand(subsystem)); + } + + private Autos() { + throw new UnsupportedOperationException("This is a utility class!"); + } +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/commands/ExampleCommand.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/commands/ExampleCommand.java new file mode 100644 index 0000000..7481d3c --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/commands/ExampleCommand.java @@ -0,0 +1,43 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot.commands; + +import frc.robot.subsystems.ExampleSubsystem; +import edu.wpi.first.wpilibj2.command.Command; + +/** An example command that uses an example subsystem. */ +public class ExampleCommand extends Command { + @SuppressWarnings({"PMD.UnusedPrivateField", "PMD.SingularField"}) + private final ExampleSubsystem m_subsystem; + + /** + * Creates a new ExampleCommand. + * + * @param subsystem The subsystem used by this command. + */ + public ExampleCommand(ExampleSubsystem subsystem) { + m_subsystem = subsystem; + // Use addRequirements() here to declare subsystem dependencies. + addRequirements(subsystem); + } + + // Called when the command is initially scheduled. + @Override + public void initialize() {} + + // Called every time the scheduler runs while the command is scheduled. + @Override + public void execute() {} + + // Called once the command ends or is interrupted. + @Override + public void end(boolean interrupted) {} + + // Returns true when the command should end. + @Override + public boolean isFinished() { + return false; + } +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/controllers/LogitechF310.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/controllers/LogitechF310.java new file mode 100644 index 0000000..74a8997 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/controllers/LogitechF310.java @@ -0,0 +1,463 @@ +package frc.controllers; + +import edu.wpi.first.wpilibj.Joystick; + +/** + * This class is used to create an LogitechF310 controller object. + *

+ * This class uses the {@code Joystick} class from the wpilibj library. + *

+ *

+ * This uses a deadband that can be set if needed. This helps control drift. + * This value can be in a range of 0 to 1. The higher the value, the more the + * stick has to move to register. This value is set in the constructor and is + * set alongside the controller ID. As a note: The deadband is only applied + * to the joystick axes. + *

+ * + * @see PS4 + * @see Xbox + * + * @see edu.wpi.first.wpilibj.Joystick + */ +public class LogitechF310 { + + // Button IDs // + + /** + * The axis ID for the left joystick x. + */ + private static final int JOYSTICK_LEFT_X = 0; + + /** + * The axis ID for the left joystick y. + */ + private static final int JOYSTICK_LEFT_Y = 1; + + /** + * The axis ID for the left trigger. + */ + private static final int TRIGGER_LEFT = 2; + + /** + * The axis ID for the right trigger. + */ + private static final int TRIGGER_RIGHT = 3; + + /** + * The axis ID for the right joystick x. + */ + private static final int JOYSTICK_RIGHT_X = 4; + + /** + * The axis ID for the right joystick y. + */ + private static final int JOYSTICK_RIGHT_Y = 5; + + /** + * The button ID for the A button. + */ + private static final int BUTTON_A = 1; + + /** + * The button ID for the B button. + */ + private static final int BUTTON_B = 2; + + /** + * The button ID for the X button. + */ + private static final int BUTTON_X = 3; + + /** + * The button ID for the Y button. + */ + private static final int BUTTON_Y = 4; + + /** + * The button ID for the left bumper. + */ + private static final int BUTTON_LEFT_BUMPER = 5; + + /** + * The button ID for the right bumper. + */ + private static final int BUTTON_RIGHT_BUMPER = 6; + + /** + * The button ID for the start button. + */ + private static final int BUTTON_START = 7; + + /** + * The button ID for the back button. + */ + private static final int BUTTON_BACK = 8; + + /** + * The controller object. + * In this case, a {@code Joystick} object. + * + * @see edu.wpi.first.wpilibj.Joystick + */ + private Joystick controller; + + /** + * The deadband value. + */ + private double deadBand; + + /** + * Constructor for the LogitechF310 class. + *

+ * This constructor is used to create a LogitechF310 object. + * This takes in the controller ID and the deadband value. + *

+ * + * @param id Controller ID (Port) + * @param deadBandValue Deadband value + */ + public LogitechF310(final int id, final double deadBandValue) { + controller = new Joystick(id); + deadBand = deadBandValue; + } + + // Deadband Method // + + /** + * Method for setting the deadband of the controller on the X and Y axes. + *

+ * This sets a threshold the joystick must pass before registering a value. + * This value can be in a range of 0 to 1. The higher the value, + * the more the joystick has to move to register. + *

+ * + * @return Deadbanded value + * + * @param value Value to be deadbanded + */ + private double deadBand(final double value) { + return Math.abs(value) < deadBand ? 0 : value; + } + + // Joystick Methods // + + /** + * Method for returning the X value of the left joystick. + * + * @return X value of the left joystick + * + * @see LogitechF310#getRightX + * @see LogitechF310#getRightY + * @see LogitechF310#getLeftY + */ + public double getLeftX() { + return deadBand(controller.getRawAxis(JOYSTICK_LEFT_X)); + } + + /** + * Method for returning the Y value of the left joystick. + * + * @return Y value of the left joystick + * + * @see LogitechF310#getRightX + * @see LogitechF310#getRightY + * @see LogitechF310#getLeftX + */ + public double getLeftY() { + return deadBand(controller.getRawAxis(JOYSTICK_LEFT_Y)); + } + + /** + * Method for returning the X value of the right joystick. + * + * @return X value of the right joystick + * + * @see LogitechF310#getRightY + * @see LogitechF310#getLeftX + * @see LogitechF310#getLeftY + */ + public double getRightX() { + return deadBand(controller.getRawAxis(JOYSTICK_RIGHT_X)); + } + + /** + * Method for returning the Y value of the right joystick. + * + * @return Y value of the right joystick + * + * @see LogitechF310#getRightX + * @see LogitechF310#getLeftX + * @see LogitechF310#getLeftY + */ + public double getRightY() { + return deadBand(controller.getRawAxis(JOYSTICK_RIGHT_Y)); + } + + // Trigger Methods // + + /** + * Method for returning the value of the left trigger. + * + * @return Value of the left trigger + * + * @see LogitechF310#getRightTrigger + */ + public double getLeftTrigger() { + return deadBand(controller.getRawAxis(TRIGGER_LEFT)); + } + + /** + * Method for returning the value of the right trigger. + * + * @return Value of the right trigger + * + * @see LogitechF310#getLeftTrigger + */ + public double getRightTrigger() { + return deadBand(controller.getRawAxis(TRIGGER_RIGHT)); + } + + // Button Methods // + + /** + * Method for returning the value of the A button. + * + * @return Value of the A button + * + * @see LogitechF310#getBButton + * @see LogitechF310#getXButton + * @see LogitechF310#getYButton + */ + public boolean getAButton() { + return controller.getRawButton(BUTTON_A); + } + + /** + * Method for returning the value of the B button. + * + * @return Value of the B button + * + * @see LogitechF310#getAButton + * @see LogitechF310#getXButton + * @see LogitechF310#getYButton + */ + public boolean getBButton() { + return controller.getRawButton(BUTTON_B); + } + + /** + * Method for returning the value of the X button. + * + * @return Value of the X button + * + * @see LogitechF310#getAButton + * @see LogitechF310#getBButton + * @see LogitechF310#getYButton + */ + public boolean getXButton() { + return controller.getRawButton(BUTTON_X); + } + + /** + * Method for returning the value of the Y button. + * + * @return Value of the Y button + * + * @see LogitechF310#getAButton + * @see LogitechF310#getBButton + * @see LogitechF310#getXButton + */ + public boolean getYButton() { + return controller.getRawButton(BUTTON_Y); + } + + /** + * Method for returning the value of the back button. + * + * @return Value of the back button + * + * @see LogitechF310#getStartButton + */ + public boolean getBackButton() { + return controller.getRawButton(BUTTON_START); + } + + /** + * Method for returning the value of the start button. + * + * @return Value of the start button + * + * @see LogitechF310#getBackButton + */ + public boolean getStartButton() { + return controller.getRawButton(BUTTON_BACK); + } + + /** + * Method for returning the value of the left bumper. + * + * @return Value of the left bumper + * + * @see LogitechF310#getRightBumper + */ + public boolean getLeftBumper() { + return controller.getRawButton(BUTTON_LEFT_BUMPER); + } + + /** + * Method for returning the value of the right bumper. + * + * @return Value of the right bumper + * + * @see LogitechF310#getLeftBumper + */ + public boolean getRightBumper() { + return controller.getRawButton(BUTTON_RIGHT_BUMPER); + } + + // D-Pad Methods // + + public enum DPad { + /** + * Up on the D-Pad. + */ + up, + + /** + * Down on the D-Pad. + */ + down, + + /** + * Right on the D-Pad. + */ + left, + + /** + * Left on the D-Pad. + */ + right, + + /** + * Up-Right on the D-Pad. + */ + upright, + + /** + * Up-Left on the D-Pad. + */ + upleft, + + /** + * Down-Right on the D-Pad. + */ + downright, + + /** + * Down-Left on the D-Pad. + */ + downleft, + + /** + * No direction on the D-Pad. + */ + none + } + + /** + * Upright D-Pad POV value. + */ + private static final int DPAD_UPRIGHT = 45; + + /** + * Right D-Pad POV value. + */ + private static final int DPAD_RIGHT = 90; + + /** + * Downright D-Pad POV value. + */ + private static final int DPAD_DOWNRIGHT = 135; + + /** + * Down POV D-Pad value. + */ + private static final int DPAD_DOWN = 180; + + /** + * Downleft D-Pad POV value. + */ + private static final int DPAD_DOWNLEFT = 225; + + /** + * Left D-Pad POV value. + */ + private static final int DPAD_LEFT = 270; + + /** + * Upleft D-Pad POV value. + */ + private static final int DPAD_UPLEFT = 315; + + /** + * Up D-Pad POV value. + */ + private static final int DPAD_UP = 360; + + /** + * Method for returning the value of the D-Pad. + * + * @return value of the D-Pad + * + * @see LogitechF310.DPad + */ + public DPad getDPad() { + switch (controller.getPOV()) { + case 0: + return DPad.up; + case DPAD_UPRIGHT: + return DPad.upright; + case DPAD_RIGHT: + return DPad.right; + case DPAD_DOWNRIGHT: + return DPad.downright; + case DPAD_DOWN: + return DPad.down; + case DPAD_DOWNLEFT: + return DPad.downleft; + case DPAD_LEFT: + return DPad.left; + case DPAD_UPLEFT: + return DPad.upleft; + case DPAD_UP: + return DPad.up; + default: + return DPad.none; + } + } + + // Rumble Methods // + + // This controller does not have rumble functionality :( + + // General Methods // + + /** + * Method for checking if the controller is connected. + * + * @return true if the controller is connected, false if not + */ + public boolean isConnected() { + return (controller.isConnected()); + } + + /** + * Method for getting the name of the controller. + * + * @return name of the controller + */ + public String getName() { + return controller.getName(); + } +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/controllers/PS4.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/controllers/PS4.java new file mode 100644 index 0000000..cef2652 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/controllers/PS4.java @@ -0,0 +1,498 @@ +package frc.controllers; + +import edu.wpi.first.wpilibj.PS4Controller; +import edu.wpi.first.wpilibj.GenericHID.RumbleType; + +/** + * This class is used to create an PS4 controller object. + *

+ * This class uses the {@code PS4Controller} class from the wpilibj library. + *

+ *

+ * This uses a deadband that can be set if needed. This helps control drift. + * This value can be in a range of 0 to 1. The higher the value, the more the + * stick has to move to register. This value is set in the constructor and is + * set alongside the controller ID. As a note: The deadband is only applied + * to the joystick axes. + *

+ * + * @see LogitechF310 + * @see Xbox + * + * @see edu.wpi.first.wpilibj.PS4Controller + */ +public class PS4 { + + /** + * The controller object. + * In this case, a {@code PS4Controller} object. + * + * @see edu.wpi.first.wpilibj.PS4Controller + */ + private PS4Controller controller; + + /** + * The deadband value. + */ + private double deadBand; + + /** + * Constructor for the PS4 class. + *

+ * This constructor is used to create a LogitechF310 object. + * This takes in the controller ID and the deadband value. + *

+ * + * @param id Controller ID (Port) + * @param deadBandValue Deadband value + */ + public PS4(final int id, final double deadBandValue) { + controller = new PS4Controller(id); + deadBand = deadBandValue; + } + + // Deadband Method // + + // Although this isn't really needed for newer controllers, + // it's still here just in case one might develop drift + + /** + * Method for setting the deadband of the controller on the X and Y axes. + *

+ * This sets a threshold the joystick must pass before registering a value. + * This value can be in a range of 0 to 1. The higher the value, + * the more the joystick has to move to register. + *

+ * + * @return Deadbanded value + * + * @param value Value to be deadbanded + */ + private double deadBand(final double value) { + return Math.abs(value) < deadBand ? 0 : value; + } + + // Joystick Methods // + + /** + * Method for returning the X value of the left joystick. + * + * @return X value of the left joystick + * + * @see PS4#getRightX + * @see PS4#getRightY + * @see PS4#getLeftY + */ + public double getLeftX() { + return deadBand(controller.getLeftX()); + } + + /** + * Method for returning the Y value of the left joystick. + * + * @return Y value of the left joystick + * + * @see PS4#getRightX + * @see PS4#getRightY + * @see PS4#getLeftX + */ + public double getLeftY() { + return deadBand(controller.getLeftY()); + } + + /** + * Method for returning the X value of the right joystick. + * + * @return X value of the right joystick + * + * @see PS4#getLeftX + * @see PS4#getRightY + * @see PS4#getLeftY + */ + public double getRightX() { + return deadBand(controller.getRightX()); + } + + /** + * Method for returning the Y value of the right joystick. + * + * @return Y value of the right joystick + * + * @see PS4#getRightX + * @see PS4#getLeftX + * @see PS4#getLeftY + */ + public double getRightY() { + return deadBand(controller.getRightY()); + } + + // Trigger Methods // + + /** + * Method for returning the value of the left trigger. + * + * @return value of the left trigger + * + * @see PS4#getRightTrigger + */ + public double getLeftTrigger() { + return deadBand(controller.getL2Axis()); + } + + /** + * Method for returning the value of the right trigger. + * + * @return value of the right trigger + * + * @see PS4#getLeftTrigger + */ + public double getRightTrigger() { + return deadBand(controller.getR2Axis()); + } + + // Button Methods // + + /** + * Method for returning the value of the X button. + * + * @return value of the X button + * + * @see PS4#getSquareButton + * @see PS4#getCircleButton + * @see PS4#getTriangleButton + * @see PS4#getShareButton + * @see PS4#getOptionsButton + * @see PS4#getPlayStationButton + * @see PS4#getTouchpadButton + */ + public boolean getXButton() { + return controller.getCrossButton(); + } + + /** + * Method for returning the value of the Square button. + * + * @return value of the Square button + * + * @see PS4#getXButton + * @see PS4#getCircleButton + * @see PS4#getTriangleButton + * @see PS4#getShareButton + * @see PS4#getOptionsButton + * @see PS4#getPlayStationButton + * @see PS4#getTouchpadButton + */ + public boolean getSquareButton() { + return controller.getSquareButton(); + } + + /** + * Method for returning the value of the Circle button. + * + * @return value of the Circle button + * + * @see PS4#getXButton + * @see PS4#getSquareButton + * @see PS4#getTriangleButton + * @see PS4#getShareButton + * @see PS4#getOptionsButton + * @see PS4#getPlayStationButton + * @see PS4#getTouchpadButton + */ + public boolean getCircleButton() { + return controller.getCircleButton(); + } + + /** + * Method for returning the value of the Triangle button. + * + * @return value of the Triangle button + * + * @see PS4#getXButton + * @see PS4#getSquareButton + * @see PS4#getCircleButton + * @see PS4#getShareButton + * @see PS4#getOptionsButton + * @see PS4#getPlayStationButton + * @see PS4#getTouchpadButton + */ + public boolean getTriangleButton() { + return controller.getTriangleButton(); + } + + /** + * Method for returning the value of the Share button. + * + * @return value of the Share button + * + * @see PS4#getXButton + * @see PS4#getSquareButton + * @see PS4#getCircleButton + * @see PS4#getTriangleButton + * @see PS4#getOptionsButton + * @see PS4#getPlayStationButton + * @see PS4#getTouchpadButton + */ + public boolean getShareButton() { + return controller.getShareButton(); + } + + /** + * Method for returning the value of the Options button. + * + * @return value of the Options button + * + * @see PS4#getXButton + * @see PS4#getSquareButton + * @see PS4#getCircleButton + * @see PS4#getTriangleButton + * @see PS4#getShareButton + * @see PS4#getPlayStationButton + * @see PS4#getTouchpadButton + */ + public boolean getOptionsButton() { + return controller.getOptionsButton(); + } + + /** + * Method for returning the value of the PlayStation button. + * + * @return value of the PlayStation button + * + * @see PS4#getXButton + * @see PS4#getSquareButton + * @see PS4#getCircleButton + * @see PS4#getTriangleButton + * @see PS4#getShareButton + * @see PS4#getOptionsButton + * @see PS4#getTouchpadButton + */ + public boolean getPlayStationButton() { + return controller.getPSButton(); + } + + /** + * Method for returning the value of the left bumper. + * + * @return value of the left bumper + * + * @see PS4#getRightBumper + */ + public boolean getLeftBumper() { + return controller.getL1Button(); + } + + /** + * Method for returning the value of the right bumper. + * + * @return value of the right bumper + * + * @see PS4#getLeftBumper + */ + public boolean getRightBumper() { + return controller.getR1Button(); + } + + /** + * Method for returning the value of the left joystick button. + * + * @return value of the left joystick button + * + * @see PS4#getRightJoystickButton + */ + public boolean getLeftJoystickButton() { + return controller.getL3Button(); + } + + /** + * Method for returning the value of the right joystick button. + * + * @return value of the right joystick button + * + * @see PS4#getLeftJoystickButton + */ + public boolean getRightJoystickButton() { + return controller.getR3Button(); + } + + // Touchpad Methods // + + /** + * Method for returning the value of the Touchpad button. + * + * @return value of the Touchpad button + * + * @see PS4#getXButton + * @see PS4#getSquareButton + * @see PS4#getCircleButton + * @see PS4#getTriangleButton + * @see PS4#getShareButton + * @see PS4#getOptionsButton + * @see PS4#getPlayStationButton + */ + public boolean getTouchpadButton() { + return controller.getTouchpad(); + } + + // There is a 'touchpad' that uses an event loop + // but for the purpose of this class, it is not needed + // It might be added in a future version if there becomes a need for it + // If you have a need for it or have added it yourself, + // Submit a pull request or submit an issue on the GitHub repository + // https://github.com/J-The-Fox/FRC-Team-5098 + + // D-Pad Methods // + + public enum DPad { + /** + * Up on the D-Pad. + */ + up, + + /** + * Down on the D-Pad. + */ + down, + + /** + * Right on the D-Pad. + */ + left, + + /** + * Left on the D-Pad. + */ + right, + + /** + * Up-Right on the D-Pad. + */ + upright, + + /** + * Up-Left on the D-Pad. + */ + upleft, + + /** + * Down-Right on the D-Pad. + */ + downright, + + /** + * Down-Left on the D-Pad. + */ + downleft, + + /** + * No direction on the D-Pad. + */ + none + } + + /** + * Upright D-Pad POV value. + */ + private static final int DPAD_UPRIGHT = 45; + + /** + * Right D-Pad POV value. + */ + private static final int DPAD_RIGHT = 90; + + /** + * Downright D-Pad POV value. + */ + private static final int DPAD_DOWNRIGHT = 135; + + /** + * Down POV D-Pad value. + */ + private static final int DPAD_DOWN = 180; + + /** + * Downleft D-Pad POV value. + */ + private static final int DPAD_DOWNLEFT = 225; + + /** + * Left D-Pad POV value. + */ + private static final int DPAD_LEFT = 270; + + /** + * Upleft D-Pad POV value. + */ + private static final int DPAD_UPLEFT = 315; + + /** + * Up D-Pad POV value. + */ + private static final int DPAD_UP = 360; + + /** + * Method for returning the value of the D-Pad. + * + * @return value of the D-Pad + * + * @see PS4.DPad + */ + public DPad getDPad() { + switch (controller.getPOV()) { + case 0: + return DPad.up; + case DPAD_UPRIGHT: + return DPad.upright; + case DPAD_RIGHT: + return DPad.right; + case DPAD_DOWNRIGHT: + return DPad.downright; + case DPAD_DOWN: + return DPad.down; + case DPAD_DOWNLEFT: + return DPad.downleft; + case DPAD_LEFT: + return DPad.left; + case DPAD_UPLEFT: + return DPad.upleft; + case DPAD_UP: + return DPad.up; + default: + return DPad.none; + } + } + + // Rumble Methods // + + /** + * Method for setting the rumble of the controller. + * + * @param type type of rumble to set + * @param value value to set the rumble to + * + * @see edu.wpi.first.wpilibj.GenericHID.RumbleType + */ + public void setRumble(final RumbleType type, final double value) { + controller.setRumble(type, value); + } + + // General Methods // + + /** + * Method for checking if the controller is connected. + * + * @return true if the controller is connected, false if not + */ + public boolean isConnected() { + return (controller.isConnected()); + } + + /** + * Method for getting the name of the controller. + * + * @return name of the controller + */ + public String getName() { + return controller.getName(); + } +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/controllers/Xbox.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/controllers/Xbox.java new file mode 100644 index 0000000..c8cc131 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/controllers/Xbox.java @@ -0,0 +1,425 @@ +package frc.controllers; + +import edu.wpi.first.wpilibj.XboxController; +import edu.wpi.first.wpilibj.GenericHID.RumbleType; + +/** + * This class is used to create an Xbox controller object. + *

+ * This class uses the {@code XboxController} class from the wpilibj library. + *

+ *

+ * This uses a deadband that can be set if needed. This helps control drift. + * This value can be in a range of 0 to 1. The higher the value, the more the + * stick has to move to register. This value is set in the constructor and is + * set alongside the controller ID. As a note: The deadband is only applied + * to the joystick axes. + *

+ * + * @see LogitechF310 + * @see PS4 + * + * @see edu.wpi.first.wpilibj.XboxController + */ +public class Xbox { + + /** + * The controller object. + * In this case, a {@code XboxController} object. + */ + private XboxController controller; + + /** + * The deadband value. + */ + private double deadBand; + + /** + * Constructor for the Xbox class. + *

+ * This constructor is used to create a LogitechF310 object. + * This takes in the controller ID and the deadband value. + *

+ * + * @param id Controller ID (Port) + * @param deadBandValue Deadband value + */ + public Xbox(final int id, final double deadBandValue) { + controller = new XboxController(id); + deadBand = deadBandValue; + } + + // Deadband Method // + + // Although this isn't really needed for newer controllers, + // it's still here just in case one might develop drift + + /** + * Method for setting the deadband of the controller on the X and Y axes. + *

+ * This sets a threshold the joystick must pass before registering a value. + * This value can be in a range of 0 to 1. The higher the value, + * the more the joystick has to move to register. + *

+ * + * @return Deadbanded value + * + * @param value Value to be deadbanded + */ + private double deadBand(final double value) { + return Math.abs(value) < deadBand ? 0 : value; + } + + // Joystick Methods // + + /** + * Method for returning the X value of the left joystick. + * + * @return X value of the left joystick + * + * @see Xbox#getRightX + * @see Xbox#getRightY + * @see Xbox#getLeftY + */ + public double getLeftX() { + return deadBand(controller.getLeftX()); + } + + /** + * Method for returning the Y value of the left joystick. + * + * @return Y value of the left joystick + * + * @see Xbox#getRightX + * @see Xbox#getRightY + * @see Xbox#getLeftX + */ + public double getLeftY() { + return deadBand(controller.getLeftY()); + } + + /** + * Method for returning the X value of the right joystick. + * + * @return X value of the right joystick + * + * @see Xbox#getRightY + * @see Xbox#getLeftX + * @see Xbox#getLeftY + */ + public double getRightX() { + return deadBand(controller.getRightX()); + } + + /** + * Method for returning the Y value of the right joystick. + * + * @return Y value of the right joystick + * + * @see Xbox#getRightX + * @see Xbox#getLeftX + * @see Xbox#getLeftY + */ + public double getRightY() { + return deadBand(controller.getRightY()); + } + + // Trigger Methods // + + /** + * Method for returning the value of the left trigger. + * + * @return value of the left trigger + * + * @see Xbox#getRightTrigger + */ + public double getLeftTrigger() { + return controller.getLeftTriggerAxis(); + } + + /** + * Method for returning the value of the right trigger. + * + * @return value of the right trigger + * + * @see Xbox#getLeftTrigger + */ + public double getRightTrigger() { + return controller.getRightTriggerAxis(); + } + + // Button Methods // + + /** + * Method for returning the value of the A button. + * + * @return value of the A button + * + * @see Xbox#getBButton + * @see Xbox#getXButton + * @see Xbox#getYButton + */ + public boolean getAButton() { + return controller.getAButton(); + } + + /** + * Method for returning the value of the B button. + * + * @return value of the B button + * + * @see Xbox#getAButton + * @see Xbox#getXButton + * @see Xbox#getYButton + */ + public boolean getBButton() { + return controller.getBButton(); + } + + /** + * Method for returning the value of the X button. + * + * @return value of the X button + * + * @see Xbox#getAButton + * @see Xbox#getBButton + * @see Xbox#getYButton + */ + public boolean getXButton() { + return controller.getXButton(); + } + + /** + * Method for returning the value of the Y button. + * + * @return value of the Y button + * + * @see Xbox#getAButton + * @see Xbox#getBButton + * @see Xbox#getXButton + */ + public boolean getYButton() { + return controller.getYButton(); + } + + /** + * Method for returning the value of the start button. + * + * @return value of the start button + * + * @see Xbox#getBackButton + */ + public boolean getStartButton() { + return controller.getStartButton(); + } + + /** + * Method for returning the value of the back button. + * + * @return value of the back button + * + * @see Xbox#getStartButton + */ + public boolean getBackButton() { + return controller.getBackButton(); + } + + /** + * Method for returning the value of the left bumper. + * + * @return value of the left bumper + * + * @see Xbox#getRightBumper + */ + public boolean getLeftBumper() { + return controller.getLeftBumper(); + } + + /** + * Method for returning the value of the right bumper. + * + * @return value of the right bumper + * + * @see Xbox#getLeftBumper + */ + public boolean getRightBumper() { + return controller.getRightBumper(); + } + + /** + * Method for returning the value of the left stick button. + * + * @return value of the left stick button + * + * @see Xbox#getRightStickButton + */ + public boolean getLeftStickButton() { + return controller.getLeftStickButton(); + } + + /** + * Method for returning the value of the right stick button. + * + * @return value of the right stick button + * + * @see Xbox#getLeftStickButton + */ + public boolean getRightStickButton() { + return controller.getRightStickButton(); + } + + // D-Pad Methods // + + public enum DPad { + /** + * Up on the D-Pad. + */ + up, + + /** + * Down on the D-Pad. + */ + down, + + /** + * Right on the D-Pad. + */ + left, + + /** + * Left on the D-Pad. + */ + right, + + /** + * Up-Right on the D-Pad. + */ + upright, + + /** + * Up-Left on the D-Pad. + */ + upleft, + + /** + * Down-Right on the D-Pad. + */ + downright, + + /** + * Down-Left on the D-Pad. + */ + downleft, + + /** + * No direction on the D-Pad. + */ + none + } + + /** + * Upright D-Pad POV value. + */ + private static final int DPAD_UPRIGHT = 45; + + /** + * Right D-Pad POV value. + */ + private static final int DPAD_RIGHT = 90; + + /** + * Downright D-Pad POV value. + */ + private static final int DPAD_DOWNRIGHT = 135; + + /** + * Down POV D-Pad value. + */ + private static final int DPAD_DOWN = 180; + + /** + * Downleft D-Pad POV value. + */ + private static final int DPAD_DOWNLEFT = 225; + + /** + * Left D-Pad POV value. + */ + private static final int DPAD_LEFT = 270; + + /** + * Upleft D-Pad POV value. + */ + private static final int DPAD_UPLEFT = 315; + + /** + * Up D-Pad POV value. + */ + private static final int DPAD_UP = 360; + + /** + * Method for returning the value of the D-Pad. + * + * @return value of the D-Pad + * + * @see Xbox.DPad + */ + public DPad getDPad() { + switch (controller.getPOV()) { + case 0: + return DPad.up; + case DPAD_UPRIGHT: + return DPad.upright; + case DPAD_RIGHT: + return DPad.right; + case DPAD_DOWNRIGHT: + return DPad.downright; + case DPAD_DOWN: + return DPad.down; + case DPAD_DOWNLEFT: + return DPad.downleft; + case DPAD_LEFT: + return DPad.left; + case DPAD_UPLEFT: + return DPad.upleft; + case DPAD_UP: + return DPad.up; + default: + return DPad.none; + } + } + + // Rumble Methods // + + /** + * Method for setting the rumble of the controller. + * + * @param type type of rumble to set + * @param value value to set the rumble to + * + * @see edu.wpi.first.wpilibj.GenericHID.RumbleType + */ + public void setRumble(final RumbleType type, final double value) { + controller.setRumble(type, value); + } + + // General Methods // + + /** + * Method for checking if the controller is connected. + * + * @return true if the controller is connected, false if not + */ + public boolean isConnected() { + return (controller.isConnected()); + } + + /** + * Method for getting the name of the controller. + * + * @return name of the controller + */ + public String getName() { + return controller.getName(); + } +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/controllers/package-info.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/controllers/package-info.java new file mode 100644 index 0000000..80793a8 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/controllers/package-info.java @@ -0,0 +1,7 @@ +/** + * Holds controller classes + *

+ * This can be used to hold both custom and pre-made controller classes. + *

+ */ +package frc.controllers; diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/subsystems/ExampleSubsystem.java b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/subsystems/ExampleSubsystem.java new file mode 100644 index 0000000..39c2a44 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/src/main/java/frc/robot/subsystems/ExampleSubsystem.java @@ -0,0 +1,48 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot.subsystems; + +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.SubsystemBase; + +public class ExampleSubsystem extends SubsystemBase { + /** Creates a new ExampleSubsystem. */ + public ExampleSubsystem() {} + + /** + * Example command factory method. + * + * @return a command + */ + public Command exampleMethodCommand() { + // Inline construction of command goes here. + // Subsystem::RunOnce implicitly requires `this` subsystem. + return runOnce(() + -> { + /* one-time action goes here */ + }); + } + + /** + * An example method querying a boolean state of the subsystem (for example, a + * digital sensor). + * + * @return value of some boolean subsystem state, such as a digital sensor. + */ + public boolean exampleCondition() { + // Query some boolean state, such as a digital sensor. + return false; + } + + @Override + public void periodic() { + // This method will be called once per scheduler run + } + + @Override + public void simulationPeriodic() { + // This method will be called once per scheduler run during simulation + } +} diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/vendordeps/Phoenix5.json b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/vendordeps/Phoenix5.json new file mode 100644 index 0000000..d0fade6 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/vendordeps/Phoenix5.json @@ -0,0 +1,151 @@ +{ + "fileName": "Phoenix5.json", + "name": "CTRE-Phoenix (v5)", + "version": "5.32.0-beta-5", + "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-beta-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-beta-latest.json" + } + ], + "javaDependencies": [ + { + "groupId": "com.ctre.phoenix", + "artifactId": "api-java", + "version": "5.32.0-beta-5" + }, + { + "groupId": "com.ctre.phoenix", + "artifactId": "wpiapi-java", + "version": "5.32.0-beta-5" + } + ], + "jniDependencies": [ + { + "groupId": "com.ctre.phoenix", + "artifactId": "cci", + "version": "5.32.0-beta-5", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "cci-sim", + "version": "5.32.0-beta-5", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + } + ], + "cppDependencies": [ + { + "groupId": "com.ctre.phoenix", + "artifactId": "wpiapi-cpp", + "version": "5.32.0-beta-5", + "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.32.0-beta-5", + "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.32.0-beta-5", + "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.32.0-beta-5", + "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.32.0-beta-5", + "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.32.0-beta-5", + "libName": "CTRE_PhoenixCCISim", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + } + ] +} \ No newline at end of file diff --git a/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/vendordeps/WPILibNewCommands.json b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/vendordeps/WPILibNewCommands.json new file mode 100644 index 0000000..67bf389 --- /dev/null +++ b/2024-2025/FreshmanProjectBots/Henrys_Command_Robot_Test/vendordeps/WPILibNewCommands.json @@ -0,0 +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" + ] + } + ] +} diff --git a/Learning_Materials/Beginner_Level/Course_Intro.txt b/2024-2025/Learning_Materials/Beginner_Level/Course_Intro.txt similarity index 100% rename from Learning_Materials/Beginner_Level/Course_Intro.txt rename to 2024-2025/Learning_Materials/Beginner_Level/Course_Intro.txt diff --git a/Learning_Materials/Beginner_Level/Java/B1DataTypes.java b/2024-2025/Learning_Materials/Beginner_Level/Java/B1DataTypes.java similarity index 100% rename from Learning_Materials/Beginner_Level/Java/B1DataTypes.java rename to 2024-2025/Learning_Materials/Beginner_Level/Java/B1DataTypes.java diff --git a/Learning_Materials/Beginner_Level/Java/B2Operators.java b/2024-2025/Learning_Materials/Beginner_Level/Java/B2Operators.java similarity index 100% rename from Learning_Materials/Beginner_Level/Java/B2Operators.java rename to 2024-2025/Learning_Materials/Beginner_Level/Java/B2Operators.java diff --git a/Learning_Materials/Beginner_Level/Java/B3IfElseStatement.java b/2024-2025/Learning_Materials/Beginner_Level/Java/B3IfElseStatement.java similarity index 100% rename from Learning_Materials/Beginner_Level/Java/B3IfElseStatement.java rename to 2024-2025/Learning_Materials/Beginner_Level/Java/B3IfElseStatement.java diff --git a/Learning_Materials/Beginner_Level/Java/B4CheckIn.java b/2024-2025/Learning_Materials/Beginner_Level/Java/B4CheckIn.java similarity index 100% rename from Learning_Materials/Beginner_Level/Java/B4CheckIn.java rename to 2024-2025/Learning_Materials/Beginner_Level/Java/B4CheckIn.java diff --git a/Learning_Materials/Beginner_Level/Java/B5Functions.java b/2024-2025/Learning_Materials/Beginner_Level/Java/B5Functions.java similarity index 100% rename from Learning_Materials/Beginner_Level/Java/B5Functions.java rename to 2024-2025/Learning_Materials/Beginner_Level/Java/B5Functions.java diff --git a/Learning_Materials/Beginner_Level/Java/B6Scope.java b/2024-2025/Learning_Materials/Beginner_Level/Java/B6Scope.java similarity index 100% rename from Learning_Materials/Beginner_Level/Java/B6Scope.java rename to 2024-2025/Learning_Materials/Beginner_Level/Java/B6Scope.java diff --git a/Learning_Materials/Beginner_Level/Java/B7ClassesAndObjects/B71ClassesAndObjects.java b/2024-2025/Learning_Materials/Beginner_Level/Java/B7ClassesAndObjects/B71ClassesAndObjects.java similarity index 100% rename from Learning_Materials/Beginner_Level/Java/B7ClassesAndObjects/B71ClassesAndObjects.java rename to 2024-2025/Learning_Materials/Beginner_Level/Java/B7ClassesAndObjects/B71ClassesAndObjects.java diff --git a/Learning_Materials/Beginner_Level/Java/B7ClassesAndObjects/B72BlueprintForHouse.java b/2024-2025/Learning_Materials/Beginner_Level/Java/B7ClassesAndObjects/B72BlueprintForHouse.java similarity index 100% rename from Learning_Materials/Beginner_Level/Java/B7ClassesAndObjects/B72BlueprintForHouse.java rename to 2024-2025/Learning_Materials/Beginner_Level/Java/B7ClassesAndObjects/B72BlueprintForHouse.java diff --git a/Learning_Materials/Beginner_Level/Java/B7ClassesAndObjects/B73RevisedBlueprintForHouse.java b/2024-2025/Learning_Materials/Beginner_Level/Java/B7ClassesAndObjects/B73RevisedBlueprintForHouse.java similarity index 100% rename from Learning_Materials/Beginner_Level/Java/B7ClassesAndObjects/B73RevisedBlueprintForHouse.java rename to 2024-2025/Learning_Materials/Beginner_Level/Java/B7ClassesAndObjects/B73RevisedBlueprintForHouse.java diff --git a/Learning_Materials/Beginner_Level/Java/B7ClassesAndObjects/B74AnotherRevisedBlueprint.java b/2024-2025/Learning_Materials/Beginner_Level/Java/B7ClassesAndObjects/B74AnotherRevisedBlueprint.java similarity index 100% rename from Learning_Materials/Beginner_Level/Java/B7ClassesAndObjects/B74AnotherRevisedBlueprint.java rename to 2024-2025/Learning_Materials/Beginner_Level/Java/B7ClassesAndObjects/B74AnotherRevisedBlueprint.java diff --git a/Learning_Materials/Beginner_Level/Java/B8FinalCheckIn.java b/2024-2025/Learning_Materials/Beginner_Level/Java/B8FinalCheckIn.java similarity index 100% rename from Learning_Materials/Beginner_Level/Java/B8FinalCheckIn.java rename to 2024-2025/Learning_Materials/Beginner_Level/Java/B8FinalCheckIn.java diff --git a/Learning_Materials/Beginner_Level/Python/B1DataTypes.py b/2024-2025/Learning_Materials/Beginner_Level/Python/B1DataTypes.py similarity index 100% rename from Learning_Materials/Beginner_Level/Python/B1DataTypes.py rename to 2024-2025/Learning_Materials/Beginner_Level/Python/B1DataTypes.py diff --git a/Learning_Materials/Beginner_Level/Python/B2Operators.py b/2024-2025/Learning_Materials/Beginner_Level/Python/B2Operators.py similarity index 100% rename from Learning_Materials/Beginner_Level/Python/B2Operators.py rename to 2024-2025/Learning_Materials/Beginner_Level/Python/B2Operators.py diff --git a/Learning_Materials/Beginner_Level/Python/B3IfElseStatement.py b/2024-2025/Learning_Materials/Beginner_Level/Python/B3IfElseStatement.py similarity index 100% rename from Learning_Materials/Beginner_Level/Python/B3IfElseStatement.py rename to 2024-2025/Learning_Materials/Beginner_Level/Python/B3IfElseStatement.py diff --git a/Learning_Materials/Beginner_Level/Python/B4CheckIn.py b/2024-2025/Learning_Materials/Beginner_Level/Python/B4CheckIn.py similarity index 100% rename from Learning_Materials/Beginner_Level/Python/B4CheckIn.py rename to 2024-2025/Learning_Materials/Beginner_Level/Python/B4CheckIn.py diff --git a/Learning_Materials/Beginner_Level/Python/B5Functions.py b/2024-2025/Learning_Materials/Beginner_Level/Python/B5Functions.py similarity index 100% rename from Learning_Materials/Beginner_Level/Python/B5Functions.py rename to 2024-2025/Learning_Materials/Beginner_Level/Python/B5Functions.py diff --git a/Learning_Materials/Beginner_Level/Python/B6Scope.py b/2024-2025/Learning_Materials/Beginner_Level/Python/B6Scope.py similarity index 100% rename from Learning_Materials/Beginner_Level/Python/B6Scope.py rename to 2024-2025/Learning_Materials/Beginner_Level/Python/B6Scope.py diff --git a/Learning_Materials/Beginner_Level/Python/B7ClassesAndObjects.py b/2024-2025/Learning_Materials/Beginner_Level/Python/B7ClassesAndObjects.py similarity index 100% rename from Learning_Materials/Beginner_Level/Python/B7ClassesAndObjects.py rename to 2024-2025/Learning_Materials/Beginner_Level/Python/B7ClassesAndObjects.py diff --git a/Learning_Materials/Beginner_Level/Python/B8FinalCheckIn.py b/2024-2025/Learning_Materials/Beginner_Level/Python/B8FinalCheckIn.py similarity index 100% rename from Learning_Materials/Beginner_Level/Python/B8FinalCheckIn.py rename to 2024-2025/Learning_Materials/Beginner_Level/Python/B8FinalCheckIn.py diff --git a/Learning_Materials/Intermediate_Level/Intermediate_Intro.txt b/2024-2025/Learning_Materials/Intermediate_Level/Intermediate_Intro.txt similarity index 100% rename from Learning_Materials/Intermediate_Level/Intermediate_Intro.txt rename to 2024-2025/Learning_Materials/Intermediate_Level/Intermediate_Intro.txt diff --git a/Learning_Materials/Intermediate_Level/Java/I0JavaCheatsheet.java b/2024-2025/Learning_Materials/Intermediate_Level/Java/I0JavaCheatsheet.java similarity index 100% rename from Learning_Materials/Intermediate_Level/Java/I0JavaCheatsheet.java rename to 2024-2025/Learning_Materials/Intermediate_Level/Java/I0JavaCheatsheet.java diff --git a/Learning_Materials/Intermediate_Level/Java/I1ConvertingDatatypes.java b/2024-2025/Learning_Materials/Intermediate_Level/Java/I1ConvertingDatatypes.java similarity index 100% rename from Learning_Materials/Intermediate_Level/Java/I1ConvertingDatatypes.java rename to 2024-2025/Learning_Materials/Intermediate_Level/Java/I1ConvertingDatatypes.java diff --git a/Learning_Materials/Intermediate_Level/Java/I2Arrays.java b/2024-2025/Learning_Materials/Intermediate_Level/Java/I2Arrays.java similarity index 100% rename from Learning_Materials/Intermediate_Level/Java/I2Arrays.java rename to 2024-2025/Learning_Materials/Intermediate_Level/Java/I2Arrays.java diff --git a/Learning_Materials/Intermediate_Level/Java/I3Loops.java b/2024-2025/Learning_Materials/Intermediate_Level/Java/I3Loops.java similarity index 100% rename from Learning_Materials/Intermediate_Level/Java/I3Loops.java rename to 2024-2025/Learning_Materials/Intermediate_Level/Java/I3Loops.java diff --git a/Learning_Materials/Intermediate_Level/Java/I4CheckIn.java b/2024-2025/Learning_Materials/Intermediate_Level/Java/I4CheckIn.java similarity index 100% rename from Learning_Materials/Intermediate_Level/Java/I4CheckIn.java rename to 2024-2025/Learning_Materials/Intermediate_Level/Java/I4CheckIn.java diff --git a/Learning_Materials/Intermediate_Level/Java/I5Enums.java b/2024-2025/Learning_Materials/Intermediate_Level/Java/I5Enums.java similarity index 100% rename from Learning_Materials/Intermediate_Level/Java/I5Enums.java rename to 2024-2025/Learning_Materials/Intermediate_Level/Java/I5Enums.java diff --git a/Learning_Materials/Intermediate_Level/Python/I1ConvertingDatatypes.py b/2024-2025/Learning_Materials/Intermediate_Level/Python/I1ConvertingDatatypes.py similarity index 100% rename from Learning_Materials/Intermediate_Level/Python/I1ConvertingDatatypes.py rename to 2024-2025/Learning_Materials/Intermediate_Level/Python/I1ConvertingDatatypes.py diff --git a/Learning_Materials/Intermediate_Level/Python/I2Lists.py b/2024-2025/Learning_Materials/Intermediate_Level/Python/I2Lists.py similarity index 100% rename from Learning_Materials/Intermediate_Level/Python/I2Lists.py rename to 2024-2025/Learning_Materials/Intermediate_Level/Python/I2Lists.py diff --git a/Learning_Materials/Robot_Level/Robot_Intro.txt b/2024-2025/Learning_Materials/Robot_Level/Robot_Intro.txt similarity index 100% rename from Learning_Materials/Robot_Level/Robot_Intro.txt rename to 2024-2025/Learning_Materials/Robot_Level/Robot_Intro.txt diff --git a/2024-2025/Tests/main-bot/.wpilib/wpilib_preferences.json b/2024-2025/Tests/main-bot/.wpilib/wpilib_preferences.json new file mode 100644 index 0000000..a5ebb07 --- /dev/null +++ b/2024-2025/Tests/main-bot/.wpilib/wpilib_preferences.json @@ -0,0 +1,6 @@ +{ + "enableCppIntellisense": false, + "currentLanguage": "java", + "projectYear": "2024", + "teamNumber": 5098 +} \ No newline at end of file diff --git a/2024-2025/Tests/main-bot/WPILib-License.md b/2024-2025/Tests/main-bot/WPILib-License.md new file mode 100644 index 0000000..e7cd597 --- /dev/null +++ b/2024-2025/Tests/main-bot/WPILib-License.md @@ -0,0 +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. diff --git a/2024-2025/Tests/main-bot/build.gradle b/2024-2025/Tests/main-bot/build.gradle new file mode 100644 index 0000000..1e8da00 --- /dev/null +++ b/2024-2025/Tests/main-bot/build.gradle @@ -0,0 +1,101 @@ +plugins { + id "java" + id "edu.wpi.first.GradleRIO" version "2024.2.1" +} + +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 = false + +// Defining my dependencies. In this case, WPILib (+ friends), and vendor libraries. +// Also defines JUnit 5. +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' +} + +test { + useJUnitPlatform() + systemProperty 'junit.jupiter.extensions.autodetection.enabled', 'true' +} + +// Simulation configuration (e.g. environment variables). +wpi.sim.addGui().defaultEnabled = true +wpi.sim.addDriverstation() + +// Setting up my Jar File. In this case, adding all libraries into the main jar ('fat 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' +} diff --git a/2024-2025/Tests/main-bot/gradle/wrapper/gradle-wrapper.properties b/2024-2025/Tests/main-bot/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..7015f6b --- /dev/null +++ b/2024-2025/Tests/main-bot/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=permwrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=permwrapper/dists diff --git a/2024-2025/Tests/main-bot/gradlew b/2024-2025/Tests/main-bot/gradlew new file mode 100644 index 0000000..1aa94a4 --- /dev/null +++ b/2024-2025/Tests/main-bot/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/2024-2025/Tests/main-bot/gradlew.bat b/2024-2025/Tests/main-bot/gradlew.bat new file mode 100644 index 0000000..6689b85 --- /dev/null +++ b/2024-2025/Tests/main-bot/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/2024-2025/Tests/main-bot/settings.gradle b/2024-2025/Tests/main-bot/settings.gradle new file mode 100644 index 0000000..3e30f84 --- /dev/null +++ b/2024-2025/Tests/main-bot/settings.gradle @@ -0,0 +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"); diff --git a/2024-2025/Tests/main-bot/src/main/deploy/example.txt b/2024-2025/Tests/main-bot/src/main/deploy/example.txt new file mode 100644 index 0000000..bb82515 --- /dev/null +++ b/2024-2025/Tests/main-bot/src/main/deploy/example.txt @@ -0,0 +1,3 @@ +Files placed in this directory will be deployed to the RoboRIO into the +'deploy' directory in the home folder. Use the 'Filesystem.getDeployDirectory' wpilib function +to get a proper path relative to the deploy directory. \ No newline at end of file diff --git a/2024-2025/Tests/main-bot/src/main/java/frc/robot/Main.java b/2024-2025/Tests/main-bot/src/main/java/frc/robot/Main.java new file mode 100644 index 0000000..8776e5d --- /dev/null +++ b/2024-2025/Tests/main-bot/src/main/java/frc/robot/Main.java @@ -0,0 +1,25 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package 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/2024-2025/Tests/main-bot/src/main/java/frc/robot/Robot.java b/2024-2025/Tests/main-bot/src/main/java/frc/robot/Robot.java new file mode 100644 index 0000000..3254294 --- /dev/null +++ b/2024-2025/Tests/main-bot/src/main/java/frc/robot/Robot.java @@ -0,0 +1,72 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot; + +import edu.wpi.first.wpilibj.TimesliceRobot; +import edu.wpi.first.wpilibj.livewindow.LiveWindow; + +/** + * The VM is configured to automatically run this class, and to call the + * functions corresponding to each mode, as described in the TimesliceRobot + * 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 TimesliceRobot { + + /** Robot constructor. */ + public Robot() { + // Run robot periodic() functions for 5 ms, and run controllers every 10 ms + super(0.005, 0.01); + + // LiveWindow causes drastic overruns in robot periodic functions that will + // interfere with controllers + LiveWindow.disableAllTelemetry(); + + // Runs for 2 ms after robot periodic functions + schedule(() -> {}, 0.002); + + // Runs for 2 ms after first controller function + schedule(() -> {}, 0.002); + + // Total usage: + // 5 ms (robot) + 2 ms (controller 1) + 2 ms (controller 2) = 9 ms + // 9 ms / 10 ms -> 90% allocated + } + + /** + * This function is run when the robot is first started up and should be used + * for any initialization code. + */ + @Override + public void robotInit() {} + + @Override + public void robotPeriodic() {} + + @Override + public void autonomousInit() {} + + @Override + public void autonomousPeriodic() {} + + @Override + public void teleopInit() {} + + @Override + public void teleopPeriodic() {} + + @Override + public void disabledInit() {} + + @Override + public void disabledPeriodic() {} + + @Override + public void testInit() {} + + @Override + public void testPeriodic() {} +} diff --git a/2024-2025/Tests/main-bot/vendordeps/WPILibNewCommands.json b/2024-2025/Tests/main-bot/vendordeps/WPILibNewCommands.json new file mode 100644 index 0000000..67bf389 --- /dev/null +++ b/2024-2025/Tests/main-bot/vendordeps/WPILibNewCommands.json @@ -0,0 +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" + ] + } + ] +} diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/.wpilib/wpilib_preferences.json b/2024-2025/Win-Nguyen/Win-Nguyen-2024/.wpilib/wpilib_preferences.json new file mode 100644 index 0000000..a5ebb07 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/.wpilib/wpilib_preferences.json @@ -0,0 +1,6 @@ +{ + "enableCppIntellisense": false, + "currentLanguage": "java", + "projectYear": "2024", + "teamNumber": 5098 +} \ No newline at end of file diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/WPILib-License.md b/2024-2025/Win-Nguyen/Win-Nguyen-2024/WPILib-License.md new file mode 100644 index 0000000..e7cd597 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/WPILib-License.md @@ -0,0 +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. diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/build.gradle b/2024-2025/Win-Nguyen/Win-Nguyen-2024/build.gradle new file mode 100644 index 0000000..1e8da00 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/build.gradle @@ -0,0 +1,101 @@ +plugins { + id "java" + id "edu.wpi.first.GradleRIO" version "2024.2.1" +} + +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 = false + +// Defining my dependencies. In this case, WPILib (+ friends), and vendor libraries. +// Also defines JUnit 5. +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' +} + +test { + useJUnitPlatform() + systemProperty 'junit.jupiter.extensions.autodetection.enabled', 'true' +} + +// Simulation configuration (e.g. environment variables). +wpi.sim.addGui().defaultEnabled = true +wpi.sim.addDriverstation() + +// Setting up my Jar File. In this case, adding all libraries into the main jar ('fat 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' +} diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/gradle/wrapper/gradle-wrapper.properties b/2024-2025/Win-Nguyen/Win-Nguyen-2024/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..7015f6b --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=permwrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=permwrapper/dists diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/gradlew b/2024-2025/Win-Nguyen/Win-Nguyen-2024/gradlew new file mode 100644 index 0000000..1aa94a4 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/gradlew.bat b/2024-2025/Win-Nguyen/Win-Nguyen-2024/gradlew.bat new file mode 100644 index 0000000..6689b85 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/settings.gradle b/2024-2025/Win-Nguyen/Win-Nguyen-2024/settings.gradle new file mode 100644 index 0000000..3e30f84 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/settings.gradle @@ -0,0 +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"); diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/deploy/example.txt b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/deploy/example.txt new file mode 100644 index 0000000..bb82515 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/deploy/example.txt @@ -0,0 +1,3 @@ +Files placed in this directory will be deployed to the RoboRIO into the +'deploy' directory in the home folder. Use the 'Filesystem.getDeployDirectory' wpilib function +to get a proper path relative to the deploy directory. \ No newline at end of file diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/deploy/pathplanner/navgrid.json b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/deploy/pathplanner/navgrid.json new file mode 100644 index 0000000..bab0da9 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/deploy/pathplanner/navgrid.json @@ -0,0 +1 @@ +{"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]]} \ No newline at end of file diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/deploy/pathplanner/paths/newpath.path b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/deploy/pathplanner/paths/newpath.path new file mode 100644 index 0000000..f7fb046 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/deploy/pathplanner/paths/newpath.path @@ -0,0 +1,49 @@ +{ + "version": 1.0, + "waypoints": [ + { + "anchor": { + "x": 0.0, + "y": 0.0 + }, + "prevControl": null, + "nextControl": { + "x": 1.0, + "y": 0.0 + }, + "isLocked": false, + "linkedName": null + }, + { + "anchor": { + "x": 1.0, + "y": 0.0 + }, + "prevControl": { + "x": 0.0, + "y": 0.0 + }, + "nextControl": null, + "isLocked": false, + "linkedName": null + } + ], + "rotationTargets": [], + "constraintZones": [], + "eventMarkers": [], + "globalConstraints": { + "maxVelocity": 3.0, + "maxAcceleration": 3.0, + "maxAngularVelocity": 540.0, + "maxAngularAcceleration": 720.0 + }, + "goalEndState": { + "velocity": 0, + "rotation": 0.0, + "rotateFast": false + }, + "reversed": false, + "folder": null, + "previewStartingState": null, + "useDefaultConstraints": false +} \ No newline at end of file diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/deploy/robot_settings.json b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/deploy/robot_settings.json new file mode 100644 index 0000000..5e10b2f --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/deploy/robot_settings.json @@ -0,0 +1,33 @@ +{ + "controllerID": 0, + "swerveDrive": { + "frontLeft": { + "driveID": 1, + "turnID": 2, + "encoderID": 10, + "posY": -0.23, + "posX": 0.36 + }, + "frontRight": { + "driveID": 7, + "turnID": 8, + "encoderID": 12, + "posY": 0.23, + "posX": 0.36 + }, + "backLeft": { + "driveID": 3, + "turnID": 4, + "encoderID": 11, + "posY": -0.23, + "posX": -0.36 + }, + "backRight": { + "driveID": 5, + "turnID": 6, + "encoderID": 9, + "posY": 0.23, + "posX": -0.36 + } + } +} \ No newline at end of file diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/CommonData.java b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/CommonData.java new file mode 100644 index 0000000..7d7148b --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/CommonData.java @@ -0,0 +1,214 @@ +package frc; + +// import frc.robot.Utility; + +/** +* Data used by other classes. +*

+* This is used to store data that needs to be accessed by multiple classes. +*

+*/ +public final class CommonData { + + // Swerve Drive Variables // + + /** + * desiredTurn is the desired angle of the robot. + */ + private static double desiredTurn; + + /** + * forwardSpeed is the desired forward and backward speed of the robot. + */ + private static double forwardSpeed; + + /** + * sideSpeed is the desired left and right speed of the robot. + */ + private static double sideSpeed; + + /** + * battenDownTheHatches is used to control the defensive stance. + */ + private static boolean battenDownTheHatches; + + // NavX Variables // + + /** + * calibrate is used to determine if the NavX should be calibrated. + */ + private static boolean calibrate; + + // Autonomous Varaibles // + + /** + * counter is used in the state machine to see what state the robot is in. + */ + private static int counter; + + private static boolean followPath; + + // private static boolean shuffleBoardPID; + + // /* + // * Would like to convert to ENUM at some point with (FL, FR, Bl, BR) - Henry + // * Used to determine which turn motor the PID settings will be tuning + // */ + // private static String tuningMotor; + + // private static boolean[] tuningMotorArray = {true, false, false, false}; + + // Constructor // + // This is set to private as this is a utility class and + // should not be instantiated + private CommonData() { + throw new UnsupportedOperationException( + "This is a utility class and cannot be instantiated"); + } + + // Accesor Methods // + + /** + * Method for returning desiredTurn. + *s + * @return desiredTurn + */ + public static double getDesiredTurn() { + return desiredTurn; + } + + /** + * Method for setting the desiredTurn. + * + * @param value value to set desiredTurn + */ + public static void setDesiredTurn(final double value) { + desiredTurn = value; + } + + /** + * Method for returning forwardSpeed. + * + * @return forwardSpeed + */ + public static double getForwardSpeed() { + return forwardSpeed; + } + + /** + * Method for setting forwardSpeed. + * + * @param value value to set forwardSpeed + */ + public static void setForwardSpeed(final double value) { + forwardSpeed = value; + } + + /** + * Method for returning sideSpeed. + * + * @return sideSpeed + */ + public static double getSideSpeed() { + return sideSpeed; + } + + /** + * Method for setting sideSpeed. + * + * @param value value to set sideSpeed + */ + public static void setSideSpeed(final double value) { + sideSpeed = value; + } + + public static void setFollowPath(final boolean value){ + followPath = value; + } + + public static boolean getFollowPath(){ + return followPath; + } + + /** + * Method for returning battenDownTheHatches. + * + * @return battenDownTheHatches + */ + public static boolean getBattenDownTheHatches() { + return battenDownTheHatches; + } + + /** + * Method for setting battenDownTheHatches. + * + * @param value value to set battenDownTheHatches + */ + public static void setBattenDownTheHatches(final boolean value) { + battenDownTheHatches = value; + } + + /** + * Method for returning calibrate. + * + * @return calibrate + */ + public static boolean getCalibrate() { + return calibrate; + } + + /** + * Method for setting calibrate. + * + * @param value value to set calibrate + */ + public static void setCalibrate(final boolean value) { + calibrate = value; + } + + /** + * Method for returning counter. + * + * @return counter + */ + public static int getCounter() { + return counter; + } + + /** + * Method for setting counter. + * + * @param value value to set counter + */ + public static void setCounter(final int value) { + counter = value; + } + + /** + * Method for displaying the PID values + * + */ + // public static boolean getShuffleBoardPID() { + // return shuffleBoardPID; + // } + /** + * Motor you are tuning + */ + // public static String setTuningMotor(String newTuningMotor) { //used to set turning motor in common data + // // If statement to make sure the chosen tuning motor is one of the four available + // if (newTuningMotor.equals("FL") || newTuningMotor.equals("FR") || newTuningMotor.equals("BL") || newTuningMotor.equals("BR")){ + // tuningMotor = newTuningMotor; + // return tuningMotor; + // } else { + // // need to add some debug statement + // Utility.printLn("That's not a tuning motor :("); + // return tuningMotor; + // } + // } + // public static String getTuningMotor() { + // return tuningMotor; + // } + // public static Boolean getTuningMotorArray() { + + // } +} diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/components/IComponent.java b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/components/IComponent.java new file mode 100644 index 0000000..2f57cf7 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/components/IComponent.java @@ -0,0 +1,18 @@ +package frc.components; + +/** + * Interface for components. + */ +public interface IComponent { + + // This is an interface. + // If a class implements any interface, + // it must have all of the methods in that interface. + // The methods defined in an interface are abstract, + // meaning they have no body. + + /** + * Method for updating the component. + */ + void update(); +} diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/components/SwerveDrive.java b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/components/SwerveDrive.java new file mode 100644 index 0000000..145dcb7 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/components/SwerveDrive.java @@ -0,0 +1,238 @@ +package frc.components; + +import com.kauailabs.navx.frc.AHRS; +import com.pathplanner.lib.controllers.PPHolonomicDriveController; +import com.pathplanner.lib.path.PathPlannerPath; +import com.pathplanner.lib.path.PathPlannerTrajectory; +import com.pathplanner.lib.util.PIDConstants; +import edu.wpi.first.math.estimator.SwerveDrivePoseEstimator; +import edu.wpi.first.math.geometry.Pose2d; +import edu.wpi.first.math.geometry.Rotation2d; +import edu.wpi.first.math.kinematics.ChassisSpeeds; +import edu.wpi.first.math.kinematics.SwerveDriveKinematics; +import edu.wpi.first.math.kinematics.SwerveModulePosition; +import edu.wpi.first.wpilibj.SPI; +import edu.wpi.first.wpilibj.Timer; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; +import frc.CommonData; +import frc.robot.Settings; +import frc.robot.Utility; + +// NOTE: All things commented out are not used. (At least not currently) + +/** + * + */ +public class SwerveDrive implements IComponent { + + /** + * Overall Equation: + * + * Motor roations per second: + * Motor rotations per minute / 60 + * + * Wheel rotations per second: + * Motor rotations per second / gear ratio + * + * Wheel radius (in ft): + * Wheel diameter (in ft) / 2 + * or + * Wheel radius (in inches) / 12 + * + * Wheel circumference (in ft): + * Wheel radius (in ft) * 2 * pi + * + * Speed (in ft/s): + * Wheel rotations per second * wheel circumference (in ft) + * + * Total Equation: + * (Motor rotations per minute / 60) / gear ratio * wheel circumference + * (in ft) + */ + + /** + * The maximum rotation of the robot. + */ + private final static double MAX_ROTATION = + (SwerveWheel.MAX_SPEED * 2 * Math.PI) / 2.7389195456 / 2; + + // The 2.7389195456 value still needs to be documented + + /** + * The offset of the yaw. + */ + double yawOffset = 0; + + /** + * The constructor for the SwerveDrive class. + * @param settings The settings for the swerve drive. + */ + public SwerveDrive(final Settings.SwerveDrive settings) { + swerveWheels = new SwerveWheel[] {new SwerveWheel(settings.frontLeft), + new SwerveWheel(settings.frontRight), + new SwerveWheel(settings.backLeft), + new SwerveWheel(settings.backRight)}; + + kinematics = new SwerveDriveKinematics( + swerveWheels[0].getSwervePos(), swerveWheels[1].getSwervePos(), + swerveWheels[2].getSwervePos(), swerveWheels[3].getSwervePos()); + + var path = PathPlannerPath.fromPathFile("newpath"); + traj = path.getTrajectory(new ChassisSpeeds(0, 0, 0), new Rotation2d(0)); + + odometry = new SwerveDrivePoseEstimator( + kinematics, Rotation2d.fromDegrees(360.0 - ahrs.getYaw()), + new SwerveModulePosition[] { + swerveWheels[0].getOdometryPosition(), + swerveWheels[1].getOdometryPosition(), + swerveWheels[2].getOdometryPosition(), + swerveWheels[3].getOdometryPosition(), + }, + new Pose2d(0, 0, new Rotation2d(0))); + + // limelightPoses[0] = new LimelightPose("limelight-back"); + // limelightPoses[1] = new LimelightPose("limelight-right"); + // limelightPoses[2] = new LimelightPose("limelight-left"); + + controller = new PPHolonomicDriveController( + new PIDConstants(0.5, 0, 0), new PIDConstants(0.05, 0, 0), + SwerveWheel.MAX_SPEED, 0.42720018726587655839358241631199); + } + + SwerveWheel[] swerveWheels; + + double leftOrRight; + double forwardOrBack; // This is the forward or back speed + + PathPlannerTrajectory traj; + PPHolonomicDriveController controller; + + private AHRS ahrs = new AHRS(SPI.Port.kMXP); + + Timer timer; + + private SwerveDriveKinematics kinematics; + private SwerveDrivePoseEstimator odometry; + + // LimelightPose[] limelightPoses = new LimelightPose[3]; + + Pose2d getCurrentPose() { return odometry.getEstimatedPosition(); } + + public void update() { + + // Put the wheels in their "X" position + // TODO: Add the common data value and finish implementing the code + // if (CommonData.getDefense) { + // } + + // Calabrate The NavX + if (CommonData.getCalibrate()) { + CommonData.setCalibrate(false); + // Reset the NavX. + ahrs.reset(); + // Reset the yaw offset after calibration. + yawOffset = ahrs.getYaw(); + } else { + odometry.update(Rotation2d.fromDegrees(360.0 - ahrs.getYaw()), + new SwerveModulePosition[] { + swerveWheels[0].getOdometryPosition(), + swerveWheels[1].getOdometryPosition(), + swerveWheels[2].getOdometryPosition(), + swerveWheels[3].getOdometryPosition(), + }); + } + + SmartDashboard.putNumber("Yaw offset", yawOffset); + + // Optional maybeClosest = + // Stream.of(limelightPoses) + // .filter(x -> x.validPose()) + // .min((left, right) -> { + // final var whereWeAre = + // odometry.getEstimatedPosition().getTranslation(); + // final var leftDistance = + // left.getPose().getTranslation().getDistance(whereWeAre); + // final var rightDistance = + // right.getPose().getTranslation().getDistance(whereWeAre); + // return leftDistance < rightDistance ? -1 + // : leftDistance > rightDistance ? 1 + // : 0; + // }); + + // if (maybeClosest.isPresent()) { + // odometry.addVisionMeasurement(maybeClosest.get().getPose(), + // Timer.getFPGATimestamp()); + // } + + if (CommonData.getFollowPath()) { + if (timer == null) { + timer = new Timer(); + timer.start(); + } + + if (timer.get() >= traj.getTotalTimeSeconds()) { + // CommonData.setFollowPath(false); + // return; + } + + var pose = getCurrentPose(); + var goal = traj.sample(timer.get()); + + StringBuilder diagnosticString = new StringBuilder(); + + diagnosticString.append("\n\nCurrent pose"); + diagnosticString.append("\nX: " + pose.getX()); + diagnosticString.append("\nY: " + pose.getY()); + diagnosticString.append("\nCurrent goal"); + diagnosticString.append("\nX: " + goal.positionMeters.getX()); + diagnosticString.append("\nY: " + goal.positionMeters.getY()); + + var speeds = + controller.calculateRobotRelativeSpeeds(getCurrentPose(), goal); + + diagnosticString.append("\nCalculated Speeds"); + diagnosticString.append("\nX/s: " + speeds.vxMetersPerSecond); + diagnosticString.append("\nY/s: " + speeds.vyMetersPerSecond); + diagnosticString.append("\nR/s: " + + (speeds.omegaRadiansPerSecond / (2 * Math.PI))); + + var states = kinematics.toSwerveModuleStates(speeds); + + diagnosticString.append("\nSwerve Wheel States"); + + for (int i = 0; i < 4; ++i) { + diagnosticString.append("\n[" + i + "] M/s" + + states[i].speedMetersPerSecond); + diagnosticString.append("\n[" + i + "] Ang" + + states[i].angle.getRotations()); + + swerveWheels[i].set(states[i]); + } + + Utility.printLn(diagnosticString.toString()); + } else { + timer = null; + + final var desiredTranslationSpeedX = + CommonData.getForwardSpeed() * + SwerveWheel.MAX_SPEED; // This code uses '+x' as toward opposing + // alliance wall + final var desiredTranslationSpeedY = + -CommonData.getSideSpeed() * + SwerveWheel.MAX_SPEED; // This code uses '+y' as toward driver's right + final var desiredRotationSpeed = + -CommonData.getDesiredTurn() * MAX_ROTATION; + var moduleStates = + kinematics.toSwerveModuleStates(ChassisSpeeds.fromFieldRelativeSpeeds( + desiredTranslationSpeedX, desiredTranslationSpeedY, + desiredRotationSpeed, Rotation2d.fromDegrees(-ahrs.getYaw()))); + + for (int i = 0; i < 4; i++) { + swerveWheels[i].set(moduleStates[i]); + } + } + } // Man that's a lot of curly braces - Justin +} // Well here's some more for ya {{}}{{{}{{{{}}}}}} - Henry +// Do you need some more? Here you go! {{{{{{{{{{{{}}}}}}}}}}}} - Ben +// :o +// >:p diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/components/SwerveWheel.java b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/components/SwerveWheel.java new file mode 100644 index 0000000..ac195b4 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/components/SwerveWheel.java @@ -0,0 +1,124 @@ +package frc.components; + +import com.ctre.phoenix6.controls.DutyCycleOut; +import com.ctre.phoenix6.controls.PositionDutyCycle; +import com.ctre.phoenix6.hardware.CANcoder; +import com.ctre.phoenix6.hardware.TalonFX; +import edu.wpi.first.math.geometry.Rotation2d; +import edu.wpi.first.math.geometry.Translation2d; +import edu.wpi.first.math.kinematics.SwerveModulePosition; +import edu.wpi.first.math.kinematics.SwerveModuleState; +import frc.robot.Settings; + +public class SwerveWheel { + /** + * Wheel circumference in meters. + */ + public final static double WHEEL_CIRCUMFERENCE = 0.3191858136; + + /** + * Drive gear ratio of the swerve modules from motor rotations to wheel + * rotations + */ + public final static double DRIVE_GEAR_RATIO = 6.55; + + /** + * The Falcon 500's maximum rated RPM. + */ + public final static int MAXIMUM_FALCON_RPM = 6380; + + /** + * The wheel's maximum rated RPM using a Falcon 500. + */ + public final static double MAXIMUM_WHEEL_RPM = + MAXIMUM_FALCON_RPM / DRIVE_GEAR_RATIO; + + /** + * The Kraken's RPM + */ + public final static int KRAKEN_RPM = 6000; + + /** + * The maximum speed of the robot in meters per second. + * + *

+ * 60 is used to convert from minutes to seconds. + *

+ */ + public final static double MAX_SPEED = + MAXIMUM_WHEEL_RPM * WHEEL_CIRCUMFERENCE / 60; + + TalonFX turnMotor; + TalonFX driveMotor; + CANcoder encoder; + + // 0.238125 Meters + // 0.365125 Meters + + Translation2d modulePos; + + double defensiveAngle; + + public SwerveWheel(Settings.SwerveDrive.Wheel settings) { + turnMotor = new TalonFX(settings.turnID); + driveMotor = new TalonFX(settings.driveID); + encoder = new CANcoder(settings.encoderID); + + modulePos = new Translation2d(settings.posX, settings.posY); + } + + public void set(SwerveModuleState swerveModuleState) { + // swerveModuleState = SwerveModuleState.optimize(swerveModuleState, + // Rotation2d.fromDegrees(turnMotor.getSelectedSensorPosition() + // / 11.3777778)); + swerveModuleState = SwerveModuleState.optimize( + swerveModuleState, + Rotation2d.fromDegrees( + encoder.getAbsolutePosition().getValueAsDouble() * 360)); + + // final double desiredTurnPos = swerveModuleState.angle.getDegrees() + // * 11.3777778; // conversion from degrees to native encoder value + final double desiredTurnPos = + swerveModuleState.angle.getDegrees() / + 360; // conversion from degrees to native encoder value + + // turnMotor.set(ControlMode.Position, desiredTurnPos); + turnMotor.setControl(new PositionDutyCycle(desiredTurnPos)); + + // driveMotor.set(ControlMode.PercentOutput, + // swerveModuleState.speedMetersPerSecond / maximumSpeed); + driveMotor.setControl( + new DutyCycleOut(swerveModuleState.speedMetersPerSecond / MAX_SPEED)); + // Using Velocity Can Be Used For Better Control But Percent Output Is + // Better Used For Practice + } + + public void defense() { + // turnMotor.set(ControlMode.Position, defensiveAngle * 11.77777777); + // driveMotor.set(ControlMode.PercentOutput, 0); + } + + public SwerveModulePosition getOdometryPosition() { + return new SwerveModulePosition( + driveMotor.getPosition().getValueAsDouble() / DRIVE_GEAR_RATIO * + WHEEL_CIRCUMFERENCE, + Rotation2d.fromRotations( + encoder.getAbsolutePosition().getValueAsDouble())); + } + + public TalonFX getTurnMotor() { return turnMotor; } + + public TalonFX getDriveMotor() { return driveMotor; } + + public Translation2d getSwervePos() { return modulePos; } + // public TalonFXConfigurator findConfig() { + // TalonFXConfigurator testValue = turnMotor.getConfigurator(); + // testValue. + // return turnMotor.getConfigurator(); + // } + + // public void battenDownTheHatches() + // { + // set(defensiveAngle, 0, 0); + // } +} diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/components/autonomous/Autonomous.java b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/components/autonomous/Autonomous.java new file mode 100644 index 0000000..814b3c7 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/components/autonomous/Autonomous.java @@ -0,0 +1,58 @@ +package frc.components.autonomous; + +import java.io.IOException; + +import edu.wpi.first.math.controller.HolonomicDriveController; +import edu.wpi.first.math.controller.PIDController; +import edu.wpi.first.math.controller.ProfiledPIDController; +import edu.wpi.first.math.trajectory.Trajectory; +import edu.wpi.first.math.trajectory.TrajectoryUtil; +import edu.wpi.first.wpilibj.DriverStation; +import edu.wpi.first.wpilibj.Filesystem; +import frc.components.IComponent; +import frc.state_machine.StateMachine; + +/** + * Autonomous component. + *

+ * This class is used for autonomous mode. + * It sets up a state machine and excutes the states contained. + *

+ *

+ * If you want to add a new state, see the constructor. + * {@link frc.components.autonomous.Autonomous#Autonomous()} + *

+ * This class implements the + * {@link frc.components.IComponent IComponent} interface. + *

+ * + * @see frc.state_machine.StateMachine + */ +public final class Autonomous implements IComponent { + + /** + * Autonomous constructor. + *

+ * This is where new states are added to the state machine. + * Any state added here will be run during autonomous in + * the order they are added. + *

+ *

+ * You can add states by using the following code: + * + *

+     * stateMachine.addState(new StateName());
+     * 
+ * + * Any added states must also exist in this directory as separate + * classes. + *

+ * + * @see frc.components.autonomous.DriveState1 + */ + public Autonomous() {} + + @Override + public void update() { + } +} diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/components/package-info.java b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/components/package-info.java new file mode 100644 index 0000000..74893cd --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/components/package-info.java @@ -0,0 +1,7 @@ +/** + * Package used to organize all of the components of the robot. + *

+ * These components can include the drivetrain, an arm, an intake, etc. + *

+ */ +package frc.components; diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/controllers/LogitechF310.java b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/controllers/LogitechF310.java new file mode 100644 index 0000000..74a8997 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/controllers/LogitechF310.java @@ -0,0 +1,463 @@ +package frc.controllers; + +import edu.wpi.first.wpilibj.Joystick; + +/** + * This class is used to create an LogitechF310 controller object. + *

+ * This class uses the {@code Joystick} class from the wpilibj library. + *

+ *

+ * This uses a deadband that can be set if needed. This helps control drift. + * This value can be in a range of 0 to 1. The higher the value, the more the + * stick has to move to register. This value is set in the constructor and is + * set alongside the controller ID. As a note: The deadband is only applied + * to the joystick axes. + *

+ * + * @see PS4 + * @see Xbox + * + * @see edu.wpi.first.wpilibj.Joystick + */ +public class LogitechF310 { + + // Button IDs // + + /** + * The axis ID for the left joystick x. + */ + private static final int JOYSTICK_LEFT_X = 0; + + /** + * The axis ID for the left joystick y. + */ + private static final int JOYSTICK_LEFT_Y = 1; + + /** + * The axis ID for the left trigger. + */ + private static final int TRIGGER_LEFT = 2; + + /** + * The axis ID for the right trigger. + */ + private static final int TRIGGER_RIGHT = 3; + + /** + * The axis ID for the right joystick x. + */ + private static final int JOYSTICK_RIGHT_X = 4; + + /** + * The axis ID for the right joystick y. + */ + private static final int JOYSTICK_RIGHT_Y = 5; + + /** + * The button ID for the A button. + */ + private static final int BUTTON_A = 1; + + /** + * The button ID for the B button. + */ + private static final int BUTTON_B = 2; + + /** + * The button ID for the X button. + */ + private static final int BUTTON_X = 3; + + /** + * The button ID for the Y button. + */ + private static final int BUTTON_Y = 4; + + /** + * The button ID for the left bumper. + */ + private static final int BUTTON_LEFT_BUMPER = 5; + + /** + * The button ID for the right bumper. + */ + private static final int BUTTON_RIGHT_BUMPER = 6; + + /** + * The button ID for the start button. + */ + private static final int BUTTON_START = 7; + + /** + * The button ID for the back button. + */ + private static final int BUTTON_BACK = 8; + + /** + * The controller object. + * In this case, a {@code Joystick} object. + * + * @see edu.wpi.first.wpilibj.Joystick + */ + private Joystick controller; + + /** + * The deadband value. + */ + private double deadBand; + + /** + * Constructor for the LogitechF310 class. + *

+ * This constructor is used to create a LogitechF310 object. + * This takes in the controller ID and the deadband value. + *

+ * + * @param id Controller ID (Port) + * @param deadBandValue Deadband value + */ + public LogitechF310(final int id, final double deadBandValue) { + controller = new Joystick(id); + deadBand = deadBandValue; + } + + // Deadband Method // + + /** + * Method for setting the deadband of the controller on the X and Y axes. + *

+ * This sets a threshold the joystick must pass before registering a value. + * This value can be in a range of 0 to 1. The higher the value, + * the more the joystick has to move to register. + *

+ * + * @return Deadbanded value + * + * @param value Value to be deadbanded + */ + private double deadBand(final double value) { + return Math.abs(value) < deadBand ? 0 : value; + } + + // Joystick Methods // + + /** + * Method for returning the X value of the left joystick. + * + * @return X value of the left joystick + * + * @see LogitechF310#getRightX + * @see LogitechF310#getRightY + * @see LogitechF310#getLeftY + */ + public double getLeftX() { + return deadBand(controller.getRawAxis(JOYSTICK_LEFT_X)); + } + + /** + * Method for returning the Y value of the left joystick. + * + * @return Y value of the left joystick + * + * @see LogitechF310#getRightX + * @see LogitechF310#getRightY + * @see LogitechF310#getLeftX + */ + public double getLeftY() { + return deadBand(controller.getRawAxis(JOYSTICK_LEFT_Y)); + } + + /** + * Method for returning the X value of the right joystick. + * + * @return X value of the right joystick + * + * @see LogitechF310#getRightY + * @see LogitechF310#getLeftX + * @see LogitechF310#getLeftY + */ + public double getRightX() { + return deadBand(controller.getRawAxis(JOYSTICK_RIGHT_X)); + } + + /** + * Method for returning the Y value of the right joystick. + * + * @return Y value of the right joystick + * + * @see LogitechF310#getRightX + * @see LogitechF310#getLeftX + * @see LogitechF310#getLeftY + */ + public double getRightY() { + return deadBand(controller.getRawAxis(JOYSTICK_RIGHT_Y)); + } + + // Trigger Methods // + + /** + * Method for returning the value of the left trigger. + * + * @return Value of the left trigger + * + * @see LogitechF310#getRightTrigger + */ + public double getLeftTrigger() { + return deadBand(controller.getRawAxis(TRIGGER_LEFT)); + } + + /** + * Method for returning the value of the right trigger. + * + * @return Value of the right trigger + * + * @see LogitechF310#getLeftTrigger + */ + public double getRightTrigger() { + return deadBand(controller.getRawAxis(TRIGGER_RIGHT)); + } + + // Button Methods // + + /** + * Method for returning the value of the A button. + * + * @return Value of the A button + * + * @see LogitechF310#getBButton + * @see LogitechF310#getXButton + * @see LogitechF310#getYButton + */ + public boolean getAButton() { + return controller.getRawButton(BUTTON_A); + } + + /** + * Method for returning the value of the B button. + * + * @return Value of the B button + * + * @see LogitechF310#getAButton + * @see LogitechF310#getXButton + * @see LogitechF310#getYButton + */ + public boolean getBButton() { + return controller.getRawButton(BUTTON_B); + } + + /** + * Method for returning the value of the X button. + * + * @return Value of the X button + * + * @see LogitechF310#getAButton + * @see LogitechF310#getBButton + * @see LogitechF310#getYButton + */ + public boolean getXButton() { + return controller.getRawButton(BUTTON_X); + } + + /** + * Method for returning the value of the Y button. + * + * @return Value of the Y button + * + * @see LogitechF310#getAButton + * @see LogitechF310#getBButton + * @see LogitechF310#getXButton + */ + public boolean getYButton() { + return controller.getRawButton(BUTTON_Y); + } + + /** + * Method for returning the value of the back button. + * + * @return Value of the back button + * + * @see LogitechF310#getStartButton + */ + public boolean getBackButton() { + return controller.getRawButton(BUTTON_START); + } + + /** + * Method for returning the value of the start button. + * + * @return Value of the start button + * + * @see LogitechF310#getBackButton + */ + public boolean getStartButton() { + return controller.getRawButton(BUTTON_BACK); + } + + /** + * Method for returning the value of the left bumper. + * + * @return Value of the left bumper + * + * @see LogitechF310#getRightBumper + */ + public boolean getLeftBumper() { + return controller.getRawButton(BUTTON_LEFT_BUMPER); + } + + /** + * Method for returning the value of the right bumper. + * + * @return Value of the right bumper + * + * @see LogitechF310#getLeftBumper + */ + public boolean getRightBumper() { + return controller.getRawButton(BUTTON_RIGHT_BUMPER); + } + + // D-Pad Methods // + + public enum DPad { + /** + * Up on the D-Pad. + */ + up, + + /** + * Down on the D-Pad. + */ + down, + + /** + * Right on the D-Pad. + */ + left, + + /** + * Left on the D-Pad. + */ + right, + + /** + * Up-Right on the D-Pad. + */ + upright, + + /** + * Up-Left on the D-Pad. + */ + upleft, + + /** + * Down-Right on the D-Pad. + */ + downright, + + /** + * Down-Left on the D-Pad. + */ + downleft, + + /** + * No direction on the D-Pad. + */ + none + } + + /** + * Upright D-Pad POV value. + */ + private static final int DPAD_UPRIGHT = 45; + + /** + * Right D-Pad POV value. + */ + private static final int DPAD_RIGHT = 90; + + /** + * Downright D-Pad POV value. + */ + private static final int DPAD_DOWNRIGHT = 135; + + /** + * Down POV D-Pad value. + */ + private static final int DPAD_DOWN = 180; + + /** + * Downleft D-Pad POV value. + */ + private static final int DPAD_DOWNLEFT = 225; + + /** + * Left D-Pad POV value. + */ + private static final int DPAD_LEFT = 270; + + /** + * Upleft D-Pad POV value. + */ + private static final int DPAD_UPLEFT = 315; + + /** + * Up D-Pad POV value. + */ + private static final int DPAD_UP = 360; + + /** + * Method for returning the value of the D-Pad. + * + * @return value of the D-Pad + * + * @see LogitechF310.DPad + */ + public DPad getDPad() { + switch (controller.getPOV()) { + case 0: + return DPad.up; + case DPAD_UPRIGHT: + return DPad.upright; + case DPAD_RIGHT: + return DPad.right; + case DPAD_DOWNRIGHT: + return DPad.downright; + case DPAD_DOWN: + return DPad.down; + case DPAD_DOWNLEFT: + return DPad.downleft; + case DPAD_LEFT: + return DPad.left; + case DPAD_UPLEFT: + return DPad.upleft; + case DPAD_UP: + return DPad.up; + default: + return DPad.none; + } + } + + // Rumble Methods // + + // This controller does not have rumble functionality :( + + // General Methods // + + /** + * Method for checking if the controller is connected. + * + * @return true if the controller is connected, false if not + */ + public boolean isConnected() { + return (controller.isConnected()); + } + + /** + * Method for getting the name of the controller. + * + * @return name of the controller + */ + public String getName() { + return controller.getName(); + } +} diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/controllers/PS4.java b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/controllers/PS4.java new file mode 100644 index 0000000..cef2652 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/controllers/PS4.java @@ -0,0 +1,498 @@ +package frc.controllers; + +import edu.wpi.first.wpilibj.PS4Controller; +import edu.wpi.first.wpilibj.GenericHID.RumbleType; + +/** + * This class is used to create an PS4 controller object. + *

+ * This class uses the {@code PS4Controller} class from the wpilibj library. + *

+ *

+ * This uses a deadband that can be set if needed. This helps control drift. + * This value can be in a range of 0 to 1. The higher the value, the more the + * stick has to move to register. This value is set in the constructor and is + * set alongside the controller ID. As a note: The deadband is only applied + * to the joystick axes. + *

+ * + * @see LogitechF310 + * @see Xbox + * + * @see edu.wpi.first.wpilibj.PS4Controller + */ +public class PS4 { + + /** + * The controller object. + * In this case, a {@code PS4Controller} object. + * + * @see edu.wpi.first.wpilibj.PS4Controller + */ + private PS4Controller controller; + + /** + * The deadband value. + */ + private double deadBand; + + /** + * Constructor for the PS4 class. + *

+ * This constructor is used to create a LogitechF310 object. + * This takes in the controller ID and the deadband value. + *

+ * + * @param id Controller ID (Port) + * @param deadBandValue Deadband value + */ + public PS4(final int id, final double deadBandValue) { + controller = new PS4Controller(id); + deadBand = deadBandValue; + } + + // Deadband Method // + + // Although this isn't really needed for newer controllers, + // it's still here just in case one might develop drift + + /** + * Method for setting the deadband of the controller on the X and Y axes. + *

+ * This sets a threshold the joystick must pass before registering a value. + * This value can be in a range of 0 to 1. The higher the value, + * the more the joystick has to move to register. + *

+ * + * @return Deadbanded value + * + * @param value Value to be deadbanded + */ + private double deadBand(final double value) { + return Math.abs(value) < deadBand ? 0 : value; + } + + // Joystick Methods // + + /** + * Method for returning the X value of the left joystick. + * + * @return X value of the left joystick + * + * @see PS4#getRightX + * @see PS4#getRightY + * @see PS4#getLeftY + */ + public double getLeftX() { + return deadBand(controller.getLeftX()); + } + + /** + * Method for returning the Y value of the left joystick. + * + * @return Y value of the left joystick + * + * @see PS4#getRightX + * @see PS4#getRightY + * @see PS4#getLeftX + */ + public double getLeftY() { + return deadBand(controller.getLeftY()); + } + + /** + * Method for returning the X value of the right joystick. + * + * @return X value of the right joystick + * + * @see PS4#getLeftX + * @see PS4#getRightY + * @see PS4#getLeftY + */ + public double getRightX() { + return deadBand(controller.getRightX()); + } + + /** + * Method for returning the Y value of the right joystick. + * + * @return Y value of the right joystick + * + * @see PS4#getRightX + * @see PS4#getLeftX + * @see PS4#getLeftY + */ + public double getRightY() { + return deadBand(controller.getRightY()); + } + + // Trigger Methods // + + /** + * Method for returning the value of the left trigger. + * + * @return value of the left trigger + * + * @see PS4#getRightTrigger + */ + public double getLeftTrigger() { + return deadBand(controller.getL2Axis()); + } + + /** + * Method for returning the value of the right trigger. + * + * @return value of the right trigger + * + * @see PS4#getLeftTrigger + */ + public double getRightTrigger() { + return deadBand(controller.getR2Axis()); + } + + // Button Methods // + + /** + * Method for returning the value of the X button. + * + * @return value of the X button + * + * @see PS4#getSquareButton + * @see PS4#getCircleButton + * @see PS4#getTriangleButton + * @see PS4#getShareButton + * @see PS4#getOptionsButton + * @see PS4#getPlayStationButton + * @see PS4#getTouchpadButton + */ + public boolean getXButton() { + return controller.getCrossButton(); + } + + /** + * Method for returning the value of the Square button. + * + * @return value of the Square button + * + * @see PS4#getXButton + * @see PS4#getCircleButton + * @see PS4#getTriangleButton + * @see PS4#getShareButton + * @see PS4#getOptionsButton + * @see PS4#getPlayStationButton + * @see PS4#getTouchpadButton + */ + public boolean getSquareButton() { + return controller.getSquareButton(); + } + + /** + * Method for returning the value of the Circle button. + * + * @return value of the Circle button + * + * @see PS4#getXButton + * @see PS4#getSquareButton + * @see PS4#getTriangleButton + * @see PS4#getShareButton + * @see PS4#getOptionsButton + * @see PS4#getPlayStationButton + * @see PS4#getTouchpadButton + */ + public boolean getCircleButton() { + return controller.getCircleButton(); + } + + /** + * Method for returning the value of the Triangle button. + * + * @return value of the Triangle button + * + * @see PS4#getXButton + * @see PS4#getSquareButton + * @see PS4#getCircleButton + * @see PS4#getShareButton + * @see PS4#getOptionsButton + * @see PS4#getPlayStationButton + * @see PS4#getTouchpadButton + */ + public boolean getTriangleButton() { + return controller.getTriangleButton(); + } + + /** + * Method for returning the value of the Share button. + * + * @return value of the Share button + * + * @see PS4#getXButton + * @see PS4#getSquareButton + * @see PS4#getCircleButton + * @see PS4#getTriangleButton + * @see PS4#getOptionsButton + * @see PS4#getPlayStationButton + * @see PS4#getTouchpadButton + */ + public boolean getShareButton() { + return controller.getShareButton(); + } + + /** + * Method for returning the value of the Options button. + * + * @return value of the Options button + * + * @see PS4#getXButton + * @see PS4#getSquareButton + * @see PS4#getCircleButton + * @see PS4#getTriangleButton + * @see PS4#getShareButton + * @see PS4#getPlayStationButton + * @see PS4#getTouchpadButton + */ + public boolean getOptionsButton() { + return controller.getOptionsButton(); + } + + /** + * Method for returning the value of the PlayStation button. + * + * @return value of the PlayStation button + * + * @see PS4#getXButton + * @see PS4#getSquareButton + * @see PS4#getCircleButton + * @see PS4#getTriangleButton + * @see PS4#getShareButton + * @see PS4#getOptionsButton + * @see PS4#getTouchpadButton + */ + public boolean getPlayStationButton() { + return controller.getPSButton(); + } + + /** + * Method for returning the value of the left bumper. + * + * @return value of the left bumper + * + * @see PS4#getRightBumper + */ + public boolean getLeftBumper() { + return controller.getL1Button(); + } + + /** + * Method for returning the value of the right bumper. + * + * @return value of the right bumper + * + * @see PS4#getLeftBumper + */ + public boolean getRightBumper() { + return controller.getR1Button(); + } + + /** + * Method for returning the value of the left joystick button. + * + * @return value of the left joystick button + * + * @see PS4#getRightJoystickButton + */ + public boolean getLeftJoystickButton() { + return controller.getL3Button(); + } + + /** + * Method for returning the value of the right joystick button. + * + * @return value of the right joystick button + * + * @see PS4#getLeftJoystickButton + */ + public boolean getRightJoystickButton() { + return controller.getR3Button(); + } + + // Touchpad Methods // + + /** + * Method for returning the value of the Touchpad button. + * + * @return value of the Touchpad button + * + * @see PS4#getXButton + * @see PS4#getSquareButton + * @see PS4#getCircleButton + * @see PS4#getTriangleButton + * @see PS4#getShareButton + * @see PS4#getOptionsButton + * @see PS4#getPlayStationButton + */ + public boolean getTouchpadButton() { + return controller.getTouchpad(); + } + + // There is a 'touchpad' that uses an event loop + // but for the purpose of this class, it is not needed + // It might be added in a future version if there becomes a need for it + // If you have a need for it or have added it yourself, + // Submit a pull request or submit an issue on the GitHub repository + // https://github.com/J-The-Fox/FRC-Team-5098 + + // D-Pad Methods // + + public enum DPad { + /** + * Up on the D-Pad. + */ + up, + + /** + * Down on the D-Pad. + */ + down, + + /** + * Right on the D-Pad. + */ + left, + + /** + * Left on the D-Pad. + */ + right, + + /** + * Up-Right on the D-Pad. + */ + upright, + + /** + * Up-Left on the D-Pad. + */ + upleft, + + /** + * Down-Right on the D-Pad. + */ + downright, + + /** + * Down-Left on the D-Pad. + */ + downleft, + + /** + * No direction on the D-Pad. + */ + none + } + + /** + * Upright D-Pad POV value. + */ + private static final int DPAD_UPRIGHT = 45; + + /** + * Right D-Pad POV value. + */ + private static final int DPAD_RIGHT = 90; + + /** + * Downright D-Pad POV value. + */ + private static final int DPAD_DOWNRIGHT = 135; + + /** + * Down POV D-Pad value. + */ + private static final int DPAD_DOWN = 180; + + /** + * Downleft D-Pad POV value. + */ + private static final int DPAD_DOWNLEFT = 225; + + /** + * Left D-Pad POV value. + */ + private static final int DPAD_LEFT = 270; + + /** + * Upleft D-Pad POV value. + */ + private static final int DPAD_UPLEFT = 315; + + /** + * Up D-Pad POV value. + */ + private static final int DPAD_UP = 360; + + /** + * Method for returning the value of the D-Pad. + * + * @return value of the D-Pad + * + * @see PS4.DPad + */ + public DPad getDPad() { + switch (controller.getPOV()) { + case 0: + return DPad.up; + case DPAD_UPRIGHT: + return DPad.upright; + case DPAD_RIGHT: + return DPad.right; + case DPAD_DOWNRIGHT: + return DPad.downright; + case DPAD_DOWN: + return DPad.down; + case DPAD_DOWNLEFT: + return DPad.downleft; + case DPAD_LEFT: + return DPad.left; + case DPAD_UPLEFT: + return DPad.upleft; + case DPAD_UP: + return DPad.up; + default: + return DPad.none; + } + } + + // Rumble Methods // + + /** + * Method for setting the rumble of the controller. + * + * @param type type of rumble to set + * @param value value to set the rumble to + * + * @see edu.wpi.first.wpilibj.GenericHID.RumbleType + */ + public void setRumble(final RumbleType type, final double value) { + controller.setRumble(type, value); + } + + // General Methods // + + /** + * Method for checking if the controller is connected. + * + * @return true if the controller is connected, false if not + */ + public boolean isConnected() { + return (controller.isConnected()); + } + + /** + * Method for getting the name of the controller. + * + * @return name of the controller + */ + public String getName() { + return controller.getName(); + } +} diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/controllers/Xbox.java b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/controllers/Xbox.java new file mode 100644 index 0000000..c8cc131 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/controllers/Xbox.java @@ -0,0 +1,425 @@ +package frc.controllers; + +import edu.wpi.first.wpilibj.XboxController; +import edu.wpi.first.wpilibj.GenericHID.RumbleType; + +/** + * This class is used to create an Xbox controller object. + *

+ * This class uses the {@code XboxController} class from the wpilibj library. + *

+ *

+ * This uses a deadband that can be set if needed. This helps control drift. + * This value can be in a range of 0 to 1. The higher the value, the more the + * stick has to move to register. This value is set in the constructor and is + * set alongside the controller ID. As a note: The deadband is only applied + * to the joystick axes. + *

+ * + * @see LogitechF310 + * @see PS4 + * + * @see edu.wpi.first.wpilibj.XboxController + */ +public class Xbox { + + /** + * The controller object. + * In this case, a {@code XboxController} object. + */ + private XboxController controller; + + /** + * The deadband value. + */ + private double deadBand; + + /** + * Constructor for the Xbox class. + *

+ * This constructor is used to create a LogitechF310 object. + * This takes in the controller ID and the deadband value. + *

+ * + * @param id Controller ID (Port) + * @param deadBandValue Deadband value + */ + public Xbox(final int id, final double deadBandValue) { + controller = new XboxController(id); + deadBand = deadBandValue; + } + + // Deadband Method // + + // Although this isn't really needed for newer controllers, + // it's still here just in case one might develop drift + + /** + * Method for setting the deadband of the controller on the X and Y axes. + *

+ * This sets a threshold the joystick must pass before registering a value. + * This value can be in a range of 0 to 1. The higher the value, + * the more the joystick has to move to register. + *

+ * + * @return Deadbanded value + * + * @param value Value to be deadbanded + */ + private double deadBand(final double value) { + return Math.abs(value) < deadBand ? 0 : value; + } + + // Joystick Methods // + + /** + * Method for returning the X value of the left joystick. + * + * @return X value of the left joystick + * + * @see Xbox#getRightX + * @see Xbox#getRightY + * @see Xbox#getLeftY + */ + public double getLeftX() { + return deadBand(controller.getLeftX()); + } + + /** + * Method for returning the Y value of the left joystick. + * + * @return Y value of the left joystick + * + * @see Xbox#getRightX + * @see Xbox#getRightY + * @see Xbox#getLeftX + */ + public double getLeftY() { + return deadBand(controller.getLeftY()); + } + + /** + * Method for returning the X value of the right joystick. + * + * @return X value of the right joystick + * + * @see Xbox#getRightY + * @see Xbox#getLeftX + * @see Xbox#getLeftY + */ + public double getRightX() { + return deadBand(controller.getRightX()); + } + + /** + * Method for returning the Y value of the right joystick. + * + * @return Y value of the right joystick + * + * @see Xbox#getRightX + * @see Xbox#getLeftX + * @see Xbox#getLeftY + */ + public double getRightY() { + return deadBand(controller.getRightY()); + } + + // Trigger Methods // + + /** + * Method for returning the value of the left trigger. + * + * @return value of the left trigger + * + * @see Xbox#getRightTrigger + */ + public double getLeftTrigger() { + return controller.getLeftTriggerAxis(); + } + + /** + * Method for returning the value of the right trigger. + * + * @return value of the right trigger + * + * @see Xbox#getLeftTrigger + */ + public double getRightTrigger() { + return controller.getRightTriggerAxis(); + } + + // Button Methods // + + /** + * Method for returning the value of the A button. + * + * @return value of the A button + * + * @see Xbox#getBButton + * @see Xbox#getXButton + * @see Xbox#getYButton + */ + public boolean getAButton() { + return controller.getAButton(); + } + + /** + * Method for returning the value of the B button. + * + * @return value of the B button + * + * @see Xbox#getAButton + * @see Xbox#getXButton + * @see Xbox#getYButton + */ + public boolean getBButton() { + return controller.getBButton(); + } + + /** + * Method for returning the value of the X button. + * + * @return value of the X button + * + * @see Xbox#getAButton + * @see Xbox#getBButton + * @see Xbox#getYButton + */ + public boolean getXButton() { + return controller.getXButton(); + } + + /** + * Method for returning the value of the Y button. + * + * @return value of the Y button + * + * @see Xbox#getAButton + * @see Xbox#getBButton + * @see Xbox#getXButton + */ + public boolean getYButton() { + return controller.getYButton(); + } + + /** + * Method for returning the value of the start button. + * + * @return value of the start button + * + * @see Xbox#getBackButton + */ + public boolean getStartButton() { + return controller.getStartButton(); + } + + /** + * Method for returning the value of the back button. + * + * @return value of the back button + * + * @see Xbox#getStartButton + */ + public boolean getBackButton() { + return controller.getBackButton(); + } + + /** + * Method for returning the value of the left bumper. + * + * @return value of the left bumper + * + * @see Xbox#getRightBumper + */ + public boolean getLeftBumper() { + return controller.getLeftBumper(); + } + + /** + * Method for returning the value of the right bumper. + * + * @return value of the right bumper + * + * @see Xbox#getLeftBumper + */ + public boolean getRightBumper() { + return controller.getRightBumper(); + } + + /** + * Method for returning the value of the left stick button. + * + * @return value of the left stick button + * + * @see Xbox#getRightStickButton + */ + public boolean getLeftStickButton() { + return controller.getLeftStickButton(); + } + + /** + * Method for returning the value of the right stick button. + * + * @return value of the right stick button + * + * @see Xbox#getLeftStickButton + */ + public boolean getRightStickButton() { + return controller.getRightStickButton(); + } + + // D-Pad Methods // + + public enum DPad { + /** + * Up on the D-Pad. + */ + up, + + /** + * Down on the D-Pad. + */ + down, + + /** + * Right on the D-Pad. + */ + left, + + /** + * Left on the D-Pad. + */ + right, + + /** + * Up-Right on the D-Pad. + */ + upright, + + /** + * Up-Left on the D-Pad. + */ + upleft, + + /** + * Down-Right on the D-Pad. + */ + downright, + + /** + * Down-Left on the D-Pad. + */ + downleft, + + /** + * No direction on the D-Pad. + */ + none + } + + /** + * Upright D-Pad POV value. + */ + private static final int DPAD_UPRIGHT = 45; + + /** + * Right D-Pad POV value. + */ + private static final int DPAD_RIGHT = 90; + + /** + * Downright D-Pad POV value. + */ + private static final int DPAD_DOWNRIGHT = 135; + + /** + * Down POV D-Pad value. + */ + private static final int DPAD_DOWN = 180; + + /** + * Downleft D-Pad POV value. + */ + private static final int DPAD_DOWNLEFT = 225; + + /** + * Left D-Pad POV value. + */ + private static final int DPAD_LEFT = 270; + + /** + * Upleft D-Pad POV value. + */ + private static final int DPAD_UPLEFT = 315; + + /** + * Up D-Pad POV value. + */ + private static final int DPAD_UP = 360; + + /** + * Method for returning the value of the D-Pad. + * + * @return value of the D-Pad + * + * @see Xbox.DPad + */ + public DPad getDPad() { + switch (controller.getPOV()) { + case 0: + return DPad.up; + case DPAD_UPRIGHT: + return DPad.upright; + case DPAD_RIGHT: + return DPad.right; + case DPAD_DOWNRIGHT: + return DPad.downright; + case DPAD_DOWN: + return DPad.down; + case DPAD_DOWNLEFT: + return DPad.downleft; + case DPAD_LEFT: + return DPad.left; + case DPAD_UPLEFT: + return DPad.upleft; + case DPAD_UP: + return DPad.up; + default: + return DPad.none; + } + } + + // Rumble Methods // + + /** + * Method for setting the rumble of the controller. + * + * @param type type of rumble to set + * @param value value to set the rumble to + * + * @see edu.wpi.first.wpilibj.GenericHID.RumbleType + */ + public void setRumble(final RumbleType type, final double value) { + controller.setRumble(type, value); + } + + // General Methods // + + /** + * Method for checking if the controller is connected. + * + * @return true if the controller is connected, false if not + */ + public boolean isConnected() { + return (controller.isConnected()); + } + + /** + * Method for getting the name of the controller. + * + * @return name of the controller + */ + public String getName() { + return controller.getName(); + } +} diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/controllers/package-info.java b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/controllers/package-info.java new file mode 100644 index 0000000..80793a8 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/controllers/package-info.java @@ -0,0 +1,7 @@ +/** + * Holds controller classes + *

+ * This can be used to hold both custom and pre-made controller classes. + *

+ */ +package frc.controllers; diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/package-info.java b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/package-info.java new file mode 100644 index 0000000..36e2dec --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/package-info.java @@ -0,0 +1,7 @@ +/** + * Main package for robot code. + *

+ * All code that is deployed to the robot would be located under this package. + *

+ */ +package frc; diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/robot/Main.java b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/robot/Main.java new file mode 100644 index 0000000..48b72ed --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/robot/Main.java @@ -0,0 +1,30 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package 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. + *

+ * + * @param args arguments from command line + */ + public static void main(final String... args) { + RobotBase.startRobot(Robot::new); + } +} diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/robot/Robot.java b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/robot/Robot.java new file mode 100644 index 0000000..cd92b7c --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/robot/Robot.java @@ -0,0 +1,179 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot; + +// Imports // +import com.fasterxml.jackson.databind.ObjectMapper; +import edu.wpi.first.wpilibj.Filesystem; +import edu.wpi.first.wpilibj.GenericHID.RumbleType; +import edu.wpi.first.wpilibj.TimedRobot; +import frc.CommonData; +import frc.components.IComponent; +import frc.components.SwerveDrive; +import frc.components.autonomous.Autonomous; +import frc.controllers.PS4; +import frc.controllers.Xbox; +import java.io.IOException; + +/** + * 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 final class Robot extends TimedRobot { + + /** + * The settings object. + * This is used to store the settings from the robot_settings.json file. + */ + private static Settings settings; + static { + ObjectMapper mapper = new ObjectMapper(); + try { + var filepath = Filesystem.getDeployDirectory().toPath().resolve( + "robot_settings.json"); + settings = mapper.readValue(filepath.toFile(), Settings.class); + } catch (IOException ex) { + System.out.println(ex.toString()); + } + } + + // Initialize the controllers // + // NOTE: This might be used for a more dynamic way of selecting controllers + + /** + * The main controller. + * This is used for the main driver. + *

+ * This is an {@code Xbox} object. + *

+ *

+ * Notice: This might be changed in the future. + *

+ */ + private Xbox controller = new Xbox(settings.controllerID, 0.1); + + /** + * The auxiliary controller. + * This is used for the auxiliary driver. + *

+ * This is a {@code PS4} object. + *

+ *

+ * Notice: This might be changed in the future. + *

+ */ + // private PS4 auxController = new PS4(settings.auxControllerID, 0); + + // Set up the components + /** + * The components array. + * This is used to store all of the components. + *

+ * This is an array of {@code IComponent} objects. + *

+ *

+ * Note: More components will be added here. + *

+ */ + private IComponent[] components = + new IComponent[] {new SwerveDrive(settings.swerveDrive)}; + + /** + * The autonomous object. + */ + private Autonomous autonomous; + + @Override + public void robotInit() { + // Calibrate the gyro before the robot runs to ensure that it is accurate + CommonData.setCalibrate(true); + CommonData.setFollowPath(false); + } + + @Override + public void robotPeriodic() { + + // For each component in the components array, update it + // This calls the update method in each of the component classes + // Since this in the robotPeriodic method, + // this will apply to all modes (autonomous, teleop, etc.) + for (var actuator : components) { + actuator.update(); + } + } + + @Override + public void autonomousInit() { + // autonomous = new Autonomous(); + + CommonData.setFollowPath(true); + } + + @Override + public void autonomousPeriodic() { + // Update the autonomous states + // autonomous.update(); + } + + @Override + public void teleopInit() { + CommonData.setFollowPath(false); + } + + @Override + public void teleopPeriodic() { + + // Update the controller values // + + // Update values for the Swerve Drive + CommonData.setCalibrate(controller.getXButton()); + CommonData.setSideSpeed(controller.getLeftX()); + CommonData.setForwardSpeed(controller.getLeftY()); + CommonData.setDesiredTurn( + Utility.snapToEdge(-controller.getRightX(), -1, 1, 0.9)); + // Utility.UIUpdate(); + } + + @Override + public void disabledInit() { + CommonData.setFollowPath(false); + + // "Turn off" all functions of the robot // + + CommonData.setDesiredTurn(0); // Set the turn speed to 0 + CommonData.setForwardSpeed(0); // Set the drive speed to 0 + + // Turn off the rumble on any controllers + controller.setRumble(RumbleType.kBothRumble, 0); + // auxController.setRumble(RumbleType.kBothRumble, 0); + + CommonData.setCounter(0); // Set the counter to 0 (used in autonomous) + } + + @Override + public void disabledPeriodic() {} + + @Override + public void testInit() { + CommonData.setFollowPath(true); + } + + @Override + public void testPeriodic() { + // Utility.printLn("Test Periodic running"); + // Utility.UIUpdate(); + } + + @Override + public void simulationInit() {} + + @Override + public void simulationPeriodic() {} +} diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/robot/Settings.java b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/robot/Settings.java new file mode 100644 index 0000000..a5c7fc3 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/robot/Settings.java @@ -0,0 +1,26 @@ +package frc.robot; + +public class Settings { + + public class SwerveDrive { + + public class Wheel { + + public int driveID; + public int turnID; + public int encoderID; + + public double posX; + public double posY; + } + + public Wheel frontLeft; + public Wheel frontRight; + public Wheel backLeft; + public Wheel backRight; + } + + public SwerveDrive swerveDrive; + + public int controllerID; +} diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/robot/Utility.java b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/robot/Utility.java new file mode 100644 index 0000000..6464012 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/robot/Utility.java @@ -0,0 +1,106 @@ +package frc.robot; + +// import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; +// import frc.CommonData; +/** + * The {@code Utility} class is used to store general methods that are used + * throughout the code. + *

+ * Current methods include: + *

+ * Additional methods may be added in the future if and when they are needed. + *

+ */ +public final class Utility { + + // Constructor // + // This is set to private as this is a utility class and + // should not be instantiated + private Utility() { + throw new UnsupportedOperationException( + "This is a utility class and cannot be instantiated"); + } + + /** + * The {@code printCounter} variable is used to count how many times the + * {@code System.out.println} method has been called. + * This is used in the {@link Utility#printLn} method. + */ + private static int printCounter = 10; + + /** + * The {@code printLn} method is used to print a message to the + * console every 50 times it is called. + * This is to slow down the messages as it overwhlems the roboRIO + * and causes the console to lag. + * + * @param messageString String to print to the console + * + * @see Utility#printCounter + */ + public static void printLn(final String messageString) { + if (printCounter == 10) { + System.out.println(messageString); + printCounter = 0; + } else { + printCounter++; + } + } + + /** + * The {@code clamp} method is used to clamp a value between a minimum and + * maximum value. + *

+ * If the value is less than the minimum, the minimum is returned. + * If the value is greater than the maximum, the maximum is returned. + * If the value is between the minimum and maximum, the value is returned. + *

+ * + * @param value Value to clamp + * @param min Minimum value + * @param max Maximum value + * + * @return The clamped value + */ + public static double clamp(final double value, final double min, + final double max) { + return value < min ? min : value > max ? max : value; + } + + /** + * Snap a value to the minimum or maximum value only if it is within a + * threshold. + * Although similar to the {@link Utility#clamp} method, + * this method is used to snap a value to the minimum or maximum value + * if it iswithin a threshold + * + * @param value Value to snap + * @param min Minimum value + * @param max Maximum value + * @param threshold Threshold to snap to + * + * @return The snapped value + */ + public static double snapToEdge(final double value, final double min, + final double max, final double threshold) { + return value < -threshold ? min : value > threshold ? max : value; + } + // public static void UIUpdate() { + // // question for later, what is the key parameter necessary for methods + // // CommonData.setTuningMotor(SmartDashboard.getString("Change Tuning + // Motor", "FL")); SmartDashboard.putString("Tuning Motor", + // CommonData.getTuningMotor()); SmartDashboard.putBoolean("FL Button", + // true); SmartDashboard.putBoolean("FR Button", false); + // SmartDashboard.putBoolean("BL Button", false); + // SmartDashboard.putBoolean("BR Button", false); + // SmartDashboard.putBooleanArray("Motor Array", + // CommonData.tuningMotorArray); + // // SmartDashboard.getNumber("P Value", "") + // // SmartDashboard. + // Utility.printLn("UI update is running"); + // } +} \ No newline at end of file diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/robot/package-info.java b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/robot/package-info.java new file mode 100644 index 0000000..20c110b --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/robot/package-info.java @@ -0,0 +1,7 @@ +/** + * Holds primary robot methods + *

+ * This package is automatically created when creating a new robot project. + *

+ */ +package frc.robot; diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/state_machine/State.java b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/state_machine/State.java new file mode 100644 index 0000000..d2450f0 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/state_machine/State.java @@ -0,0 +1,37 @@ +package frc.state_machine; + +/** +* Abstract class used to create states for the state machine. +*/ +public abstract class State { + + // Imported from 2022-2023 code + + /** + * Method called when a state is entered. + */ + public void onEnter() { + } + + /** + * Method called when a state is exited. + */ + public void onExit() { + } + + /** + * Method called to check if a state is valid. + * @return boolean + */ + public boolean isValid() { + return true; + } + + /** + * Method called to run a state. + * This method should return true when the state is finished + * + * @return boolean + */ + public abstract boolean run(); +} diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/state_machine/StateMachine.java b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/state_machine/StateMachine.java new file mode 100644 index 0000000..3d9e73f --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/state_machine/StateMachine.java @@ -0,0 +1,52 @@ +package frc.state_machine; + +import java.util.ArrayList; +import java.util.List; + +/** + * State Machine class for controlling a state machine. + * This is mainly used during auto. + * + * @see frc.components.autonomous.Autonomous + */ +public final class StateMachine { + + /** + * The current state of the state machine. + */ + private State currentState; + + /** + * The list of states to run. + */ + private List states = new ArrayList(); + + /** + * Adds a state to the state machine. + * + * @param state The state to add to the state machine. + */ + public void addState(final State state) { + states.add(state); + } + + /** + * Method called to run the state machine. + */ + public void run() { + if (!states.isEmpty()) { + if (currentState == null && states.get(0).isValid()) { + currentState = states.get(0); + currentState.onEnter(); + states.remove(0); + } + } + + if (currentState != null) { + if (currentState.run()) { + currentState.onExit(); + currentState = null; + } + } + } +} diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/state_machine/package-info.java b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/state_machine/package-info.java new file mode 100644 index 0000000..7486149 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/src/main/java/frc/state_machine/package-info.java @@ -0,0 +1,7 @@ +/** + * State machine package. + *

+ * This package contains all of the code for the state machine. + *

+ */ +package frc.state_machine; diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/vendordeps/NavX.json b/2024-2025/Win-Nguyen/Win-Nguyen-2024/vendordeps/NavX.json new file mode 100644 index 0000000..e978a5f --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/vendordeps/NavX.json @@ -0,0 +1,40 @@ +{ + "fileName": "NavX.json", + "name": "NavX", + "version": "2024.1.0", + "uuid": "cb311d09-36e9-4143-a032-55bb2b94443b", + "frcYear": "2024", + "mavenUrls": [ + "https://dev.studica.com/maven/release/2024/" + ], + "jsonUrl": "https://dev.studica.com/releases/2024/NavX.json", + "javaDependencies": [ + { + "groupId": "com.kauailabs.navx.frc", + "artifactId": "navx-frc-java", + "version": "2024.1.0" + } + ], + "jniDependencies": [], + "cppDependencies": [ + { + "groupId": "com.kauailabs.navx.frc", + "artifactId": "navx-frc-cpp", + "version": "2024.1.0", + "headerClassifier": "headers", + "sourcesClassifier": "sources", + "sharedLibrary": false, + "libName": "navx_frc", + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena", + "linuxraspbian", + "linuxarm32", + "linuxarm64", + "linuxx86-64", + "osxuniversal", + "windowsx86-64" + ] + } + ] +} \ No newline at end of file diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/vendordeps/PathplannerLib.json b/2024-2025/Win-Nguyen/Win-Nguyen-2024/vendordeps/PathplannerLib.json new file mode 100644 index 0000000..6dc648d --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/vendordeps/PathplannerLib.json @@ -0,0 +1,38 @@ +{ + "fileName": "PathplannerLib.json", + "name": "PathplannerLib", + "version": "2024.2.8", + "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.2.8" + } + ], + "jniDependencies": [], + "cppDependencies": [ + { + "groupId": "com.pathplanner.lib", + "artifactId": "PathplannerLib-cpp", + "version": "2024.2.8", + "libName": "PathplannerLib", + "headerClassifier": "headers", + "sharedLibrary": false, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal", + "linuxathena", + "linuxarm32", + "linuxarm64" + ] + } + ] +} \ No newline at end of file diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/vendordeps/Phoenix6.json b/2024-2025/Win-Nguyen/Win-Nguyen-2024/vendordeps/Phoenix6.json new file mode 100644 index 0000000..2b7d172 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/vendordeps/Phoenix6.json @@ -0,0 +1,339 @@ +{ + "fileName": "Phoenix6.json", + "name": "CTRE-Phoenix (v6)", + "version": "24.2.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.2.0" + } + ], + "jniDependencies": [ + { + "groupId": "com.ctre.phoenix6", + "artifactId": "tools", + "version": "24.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "tools-sim", + "version": "24.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simTalonSRX", + "version": "24.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simTalonFX", + "version": "24.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simVictorSPX", + "version": "24.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simPigeonIMU", + "version": "24.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simCANCoder", + "version": "24.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProTalonFX", + "version": "24.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANcoder", + "version": "24.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProPigeon2", + "version": "24.2.0", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + } + ], + "cppDependencies": [ + { + "groupId": "com.ctre.phoenix6", + "artifactId": "wpiapi-cpp", + "version": "24.2.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.2.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.2.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.2.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.2.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.2.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.2.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.2.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.2.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.2.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.2.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.2.0", + "libName": "CTRE_SimProPigeon2", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + } + ] +} \ No newline at end of file diff --git a/2024-2025/Win-Nguyen/Win-Nguyen-2024/vendordeps/WPILibNewCommands.json b/2024-2025/Win-Nguyen/Win-Nguyen-2024/vendordeps/WPILibNewCommands.json new file mode 100644 index 0000000..67bf389 --- /dev/null +++ b/2024-2025/Win-Nguyen/Win-Nguyen-2024/vendordeps/WPILibNewCommands.json @@ -0,0 +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" + ] + } + ] +} diff --git a/2024-2025/main-bot/WPILib-License.md b/2024-2025/main-bot/WPILib-License.md new file mode 100644 index 0000000..e7cd597 --- /dev/null +++ b/2024-2025/main-bot/WPILib-License.md @@ -0,0 +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. diff --git a/2024-2025/main-bot/build.gradle b/2024-2025/main-bot/build.gradle new file mode 100644 index 0000000..b15eee5 --- /dev/null +++ b/2024-2025/main-bot/build.gradle @@ -0,0 +1,104 @@ +plugins { + id "java" + id "edu.wpi.first.GradleRIO" version "2025.2.1" +} + +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' + deleteOldFiles = true // Change to true to delete files on roboRIO that no + // longer exist in deploy directory of this project + } + } + } + } +} + +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 = false + +// Defining my dependencies. In this case, WPILib (+ friends), and vendor libraries. +// Also defines JUnit 5. +dependencies { + annotationProcessor wpi.java.deps.wpilibAnnotations() + implementation wpi.java.deps.wpilib() + implementation wpi.java.vendor.java() + + roborioDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.roborio) + roborioDebug wpi.java.vendor.jniDebug(wpi.platforms.roborio) + + 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' +} + +test { + useJUnitPlatform() + systemProperty 'junit.jupiter.extensions.autodetection.enabled', 'true' +} + +// Simulation configuration (e.g. environment variables). +wpi.sim.addGui().defaultEnabled = true +wpi.sim.addDriverstation() + +// Setting up my Jar File. In this case, adding all libraries into the main jar ('fat 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' +} diff --git a/2024-2025/main-bot/gradle/wrapper/gradle-wrapper.properties b/2024-2025/main-bot/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..8e975a5 --- /dev/null +++ b/2024-2025/main-bot/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=permwrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=permwrapper/dists diff --git a/2024-2025/main-bot/gradlew b/2024-2025/main-bot/gradlew new file mode 100755 index 0000000..f5feea6 --- /dev/null +++ b/2024-2025/main-bot/gradlew @@ -0,0 +1,252 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/2024-2025/main-bot/gradlew.bat b/2024-2025/main-bot/gradlew.bat new file mode 100644 index 0000000..9b42019 --- /dev/null +++ b/2024-2025/main-bot/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/2024-2025/main-bot/networktables.json b/2024-2025/main-bot/networktables.json new file mode 100644 index 0000000..60b0742 --- /dev/null +++ b/2024-2025/main-bot/networktables.json @@ -0,0 +1 @@ +[] diff --git a/2024-2025/main-bot/settings.gradle b/2024-2025/main-bot/settings.gradle new file mode 100644 index 0000000..3bc070a --- /dev/null +++ b/2024-2025/main-bot/settings.gradle @@ -0,0 +1,30 @@ +import org.gradle.internal.os.OperatingSystem + +pluginManagement { + repositories { + mavenLocal() + gradlePluginPortal() + String frcYear = '2025' + 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/2024-2025/main-bot/simgui-ds.json b/2024-2025/main-bot/simgui-ds.json new file mode 100644 index 0000000..4a63cc1 --- /dev/null +++ b/2024-2025/main-bot/simgui-ds.json @@ -0,0 +1,97 @@ +{ + "System Joysticks": { + "window": { + "enabled": false + } + }, + "keyboardJoysticks": [ + { + "axisConfig": [ + { + "decKey": 65, + "incKey": 68 + }, + { + "decKey": 87, + "incKey": 83 + }, + { + "decKey": 69, + "decayRate": 0.0, + "incKey": 82, + "keyRate": 0.009999999776482582 + } + ], + "axisCount": 3, + "buttonCount": 4, + "buttonKeys": [ + 90, + 88, + 67, + 86 + ], + "povConfig": [ + { + "key0": 328, + "key135": 323, + "key180": 322, + "key225": 321, + "key270": 324, + "key315": 327, + "key45": 329, + "key90": 326 + } + ], + "povCount": 1 + }, + { + "axisConfig": [ + { + "decKey": 74, + "incKey": 76 + }, + { + "decKey": 73, + "incKey": 75 + } + ], + "axisCount": 2, + "buttonCount": 4, + "buttonKeys": [ + 77, + 44, + 46, + 47 + ], + "povCount": 0 + }, + { + "axisConfig": [ + { + "decKey": 263, + "incKey": 262 + }, + { + "decKey": 265, + "incKey": 264 + } + ], + "axisCount": 2, + "buttonCount": 6, + "buttonKeys": [ + 260, + 268, + 266, + 261, + 269, + 267 + ], + "povCount": 0 + }, + { + "axisCount": 0, + "buttonCount": 0, + "povCount": 0 + } + ] +} diff --git a/2024-2025/main-bot/simgui-window.json b/2024-2025/main-bot/simgui-window.json new file mode 100644 index 0000000..785b5de --- /dev/null +++ b/2024-2025/main-bot/simgui-window.json @@ -0,0 +1,83 @@ +{ + "Docking": { + "Data": [] + }, + "MainWindow": { + "GLOBAL": { + "font": "Proggy Dotted", + "fps": "120", + "height": "1057", + "maximized": "1", + "style": "0", + "userScale": "2", + "width": "1920", + "xpos": "1920", + "ypos": "23" + } + }, + "Table": { + "0xE56EC1C2,4": { + "Column 0 Weight": "1.0000", + "Column 1 Weight": "1.0000", + "Column 2 Weight": "1.0000", + "Column 3 Weight": "1.0000" + } + }, + "Window": { + "###FMS": { + "Collapsed": "0", + "Pos": "10,346", + "Size": "169,184" + }, + "###Joysticks": { + "Collapsed": "0", + "Pos": "149,27", + "Size": "796,234" + }, + "###NetworkTables": { + "Collapsed": "1", + "Pos": "28,566", + "Size": "750,440" + }, + "###NetworkTables Info": { + "Collapsed": "1", + "Pos": "26,593", + "Size": "750,145" + }, + "###Other Devices": { + "Collapsed": "0", + "Pos": "1650,32", + "Size": "250,695" + }, + "###Plot <0>": { + "Collapsed": "0", + "Pos": "948,27", + "Size": "700,400" + }, + "###Plot <1>": { + "Collapsed": "0", + "Pos": "949,433", + "Size": "700,400" + }, + "###System Joysticks": { + "Collapsed": "0", + "Pos": "12,348", + "Size": "192,218" + }, + "###Timing": { + "Collapsed": "0", + "Pos": "5,150", + "Size": "135,173" + }, + "Debug##Default": { + "Collapsed": "0", + "Pos": "60,60", + "Size": "400,400" + }, + "Robot State": { + "Collapsed": "0", + "Pos": "5,20", + "Size": "99,116" + } + } +} diff --git a/2024-2025/main-bot/simgui.json b/2024-2025/main-bot/simgui.json new file mode 100644 index 0000000..307e52a --- /dev/null +++ b/2024-2025/main-bot/simgui.json @@ -0,0 +1,95 @@ +{ + "HALProvider": { + "Other Devices": { + "Talon FX (v6)[12]": { + "header": { + "open": true + } + }, + "Talon FX (v6)[13]": { + "header": { + "open": true + } + } + } + }, + "NTProvider": { + "types": { + "/FMSInfo": "FMSInfo", + "/Pose": "Field2d", + "/SmartDashboard/Alerts": "Alerts", + "/SmartDashboard/Auto Chooser": "String Chooser", + "/SmartDashboard/Module 0": "Mechanism2d", + "/SmartDashboard/Module 1": "Mechanism2d", + "/SmartDashboard/Module 2": "Mechanism2d", + "/SmartDashboard/Module 3": "Mechanism2d" + } + }, + "NetworkTables": { + "Persistent Values": { + "open": false + }, + "Retained Values": { + "open": false + }, + "Transitory Values": { + "open": false + }, + "transitory": { + "DriveState": { + "ChassisSpeeds##v_/DriveState/Speeds": { + "open": true + } + }, + "SmartDashboard": { + "Alerts": { + "open": true + }, + "Auto Chooser": { + "open": true + }, + "Module 0": { + "open": true + }, + "Module 1": { + "open": true + }, + "Module 2": { + "open": true + }, + "Module 3": { + "open": true + } + } + } + }, + "NetworkTables Info": { + "visible": true + }, + "Plot": { + "Plot <0>": { + "plots": [ + { + "backgroundColor": [ + 0.0, + 0.0, + 0.0, + 0.8500000238418579 + ], + "height": 338, + "series": [ + { + "color": [ + 0.2980392277240753, + 0.44705885648727417, + 0.6901960968971252, + 1.0 + ], + "id": "CANMotor:Talon FX (v6)[12]-motorVoltage" + } + ] + } + ] + } + } +} diff --git a/2024-2025/main-bot/src/main/deploy/example.txt b/2024-2025/main-bot/src/main/deploy/example.txt new file mode 100644 index 0000000..bb82515 --- /dev/null +++ b/2024-2025/main-bot/src/main/deploy/example.txt @@ -0,0 +1,3 @@ +Files placed in this directory will be deployed to the RoboRIO into the +'deploy' directory in the home folder. Use the 'Filesystem.getDeployDirectory' wpilib function +to get a proper path relative to the deploy directory. \ No newline at end of file diff --git a/2024-2025/main-bot/src/main/deploy/pathplanner/autos/Long Curve Test Auto.auto b/2024-2025/main-bot/src/main/deploy/pathplanner/autos/Long Curve Test Auto.auto new file mode 100644 index 0000000..11e4ee9 --- /dev/null +++ b/2024-2025/main-bot/src/main/deploy/pathplanner/autos/Long Curve Test Auto.auto @@ -0,0 +1,19 @@ +{ + "version": "2025.0", + "command": { + "type": "sequential", + "data": { + "commands": [ + { + "type": "path", + "data": { + "pathName": "Command Example Path" + } + } + ] + } + }, + "resetOdom": true, + "folder": null, + "choreoAuto": false +} \ No newline at end of file diff --git a/2024-2025/main-bot/src/main/deploy/pathplanner/autos/Short PathPlanner Test.auto b/2024-2025/main-bot/src/main/deploy/pathplanner/autos/Short PathPlanner Test.auto new file mode 100644 index 0000000..f94ce95 --- /dev/null +++ b/2024-2025/main-bot/src/main/deploy/pathplanner/autos/Short PathPlanner Test.auto @@ -0,0 +1,19 @@ +{ + "version": "2025.0", + "command": { + "type": "sequential", + "data": { + "commands": [ + { + "type": "path", + "data": { + "pathName": "Fun Short Path" + } + } + ] + } + }, + "resetOdom": true, + "folder": null, + "choreoAuto": false +} \ No newline at end of file diff --git a/2024-2025/main-bot/src/main/deploy/pathplanner/navgrid.json b/2024-2025/main-bot/src/main/deploy/pathplanner/navgrid.json new file mode 100644 index 0000000..23e0db9 --- /dev/null +++ b/2024-2025/main-bot/src/main/deploy/pathplanner/navgrid.json @@ -0,0 +1 @@ +{"field_size":{"x":17.548,"y":8.052},"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],[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,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,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,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,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,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,false,false,false,true,true],[true,true,false,false,false,false,false,false,false,false,false,false,false,false,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,true,true,true,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,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,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,true,true],[true,true,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,true,true,true,true,true,true,true,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,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,true,true,true,false,false,false,false,false,false,false,false,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,true,true],[true,true,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,true,true,true,true,true,false,false,false,false,false,false,false,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,true,true],[true,true,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,true,true,true,true,true,false,false,false,false,false,false,false,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,true,true],[true,true,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,true,true,true,true,true,false,false,false,false,false,false,false,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,true,true],[true,true,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,true,true,true,false,false,false,false,false,false,false,false,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,true,true],[true,true,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,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,true,true],[true,true,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,true,true,true,true,true,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,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,true,true,true,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,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,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,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,false,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,false,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,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]]} \ No newline at end of file diff --git a/2024-2025/main-bot/src/main/deploy/pathplanner/paths/Command Example Path.path b/2024-2025/main-bot/src/main/deploy/pathplanner/paths/Command Example Path.path new file mode 100644 index 0000000..cd58fd4 --- /dev/null +++ b/2024-2025/main-bot/src/main/deploy/pathplanner/paths/Command Example Path.path @@ -0,0 +1,70 @@ +{ + "version": "2025.0", + "waypoints": [ + { + "anchor": { + "x": 2.0, + "y": 7.0 + }, + "prevControl": null, + "nextControl": { + "x": 3.0, + "y": 7.0 + }, + "isLocked": false, + "linkedName": null + }, + { + "anchor": { + "x": 6.58125, + "y": 6.74464897260274 + }, + "prevControl": { + "x": 5.860809075342465, + "y": 7.706271404109589 + }, + "nextControl": { + "x": 7.301690924657534, + "y": 5.783026541095891 + }, + "isLocked": false, + "linkedName": null + }, + { + "anchor": { + "x": 6.881763698630137, + "y": 3.1535102739726026 + }, + "prevControl": { + "x": 6.971917808219178, + "y": 4.235359589041096 + }, + "nextControl": null, + "isLocked": false, + "linkedName": null + } + ], + "rotationTargets": [], + "constraintZones": [], + "pointTowardsZones": [], + "eventMarkers": [], + "globalConstraints": { + "maxVelocity": 3.0, + "maxAcceleration": 3.0, + "maxAngularVelocity": 540.0, + "maxAngularAcceleration": 720.0, + "nominalVoltage": 12.0, + "unlimited": false + }, + "goalEndState": { + "velocity": 0, + "rotation": 0.0 + }, + "reversed": false, + "folder": null, + "idealStartingState": { + "velocity": 0, + "rotation": 0.0 + }, + "useDefaultConstraints": true +} \ No newline at end of file diff --git a/2024-2025/main-bot/src/main/deploy/pathplanner/paths/Fun Short Path.path b/2024-2025/main-bot/src/main/deploy/pathplanner/paths/Fun Short Path.path new file mode 100644 index 0000000..95b3ae8 --- /dev/null +++ b/2024-2025/main-bot/src/main/deploy/pathplanner/paths/Fun Short Path.path @@ -0,0 +1,54 @@ +{ + "version": "2025.0", + "waypoints": [ + { + "anchor": { + "x": 2.0, + "y": 7.0 + }, + "prevControl": null, + "nextControl": { + "x": 3.0, + "y": 7.0 + }, + "isLocked": false, + "linkedName": null + }, + { + "anchor": { + "x": 4.1470890410958905, + "y": 5.587671232876712 + }, + "prevControl": { + "x": 3.1470890410958905, + "y": 5.587671232876712 + }, + "nextControl": null, + "isLocked": false, + "linkedName": null + } + ], + "rotationTargets": [], + "constraintZones": [], + "pointTowardsZones": [], + "eventMarkers": [], + "globalConstraints": { + "maxVelocity": 3.0, + "maxAcceleration": 3.0, + "maxAngularVelocity": 540.0, + "maxAngularAcceleration": 720.0, + "nominalVoltage": 12.0, + "unlimited": false + }, + "goalEndState": { + "velocity": 0, + "rotation": 178.8622775462112 + }, + "reversed": false, + "folder": null, + "idealStartingState": { + "velocity": 0, + "rotation": 0.0 + }, + "useDefaultConstraints": true +} \ No newline at end of file diff --git a/2024-2025/main-bot/src/main/deploy/pathplanner/paths/New Path.path b/2024-2025/main-bot/src/main/deploy/pathplanner/paths/New Path.path new file mode 100644 index 0000000..8ea16a6 --- /dev/null +++ b/2024-2025/main-bot/src/main/deploy/pathplanner/paths/New Path.path @@ -0,0 +1,54 @@ +{ + "version": "2025.0", + "waypoints": [ + { + "anchor": { + "x": 2.0, + "y": 7.0 + }, + "prevControl": null, + "nextControl": { + "x": 3.0, + "y": 7.0 + }, + "isLocked": false, + "linkedName": null + }, + { + "anchor": { + "x": 3.4408818493150686, + "y": 4.009974315068493 + }, + "prevControl": { + "x": 2.4408818493150686, + "y": 4.009974315068493 + }, + "nextControl": null, + "isLocked": false, + "linkedName": null + } + ], + "rotationTargets": [], + "constraintZones": [], + "pointTowardsZones": [], + "eventMarkers": [], + "globalConstraints": { + "maxVelocity": 3.0, + "maxAcceleration": 3.0, + "maxAngularVelocity": 540.0, + "maxAngularAcceleration": 720.0, + "nominalVoltage": 12.0, + "unlimited": false + }, + "goalEndState": { + "velocity": 0, + "rotation": 0.0 + }, + "reversed": false, + "folder": null, + "idealStartingState": { + "velocity": 0, + "rotation": 0.0 + }, + "useDefaultConstraints": true +} \ No newline at end of file diff --git a/2024-2025/main-bot/src/main/deploy/pathplanner/settings.json b/2024-2025/main-bot/src/main/deploy/pathplanner/settings.json new file mode 100644 index 0000000..1ce63a6 --- /dev/null +++ b/2024-2025/main-bot/src/main/deploy/pathplanner/settings.json @@ -0,0 +1,32 @@ +{ + "robotWidth": 0.9, + "robotLength": 0.9, + "holonomicMode": true, + "pathFolders": [], + "autoFolders": [], + "defaultMaxVel": 3.0, + "defaultMaxAccel": 3.0, + "defaultMaxAngVel": 540.0, + "defaultMaxAngAccel": 720.0, + "defaultNominalVoltage": 12.0, + "robotMass": 74.088, + "robotMOI": 6.883, + "robotTrackwidth": 0.546, + "driveWheelRadius": 0.051, + "driveGearing": 5.143, + "maxDriveSpeed": 5.45, + "driveMotorType": "krakenX60", + "driveCurrentLimit": 60.0, + "wheelCOF": 1.2, + "flModuleX": 0.273, + "flModuleY": 0.273, + "frModuleX": 0.273, + "frModuleY": -0.273, + "blModuleX": -0.273, + "blModuleY": 0.273, + "brModuleX": -0.273, + "brModuleY": -0.273, + "bumperOffsetX": 0.0, + "bumperOffsetY": 0.0, + "robotFeatures": [] +} \ No newline at end of file diff --git a/2024-2025/main-bot/src/main/java/frc/.clang-format b/2024-2025/main-bot/src/main/java/frc/.clang-format new file mode 100644 index 0000000..bdb418e --- /dev/null +++ b/2024-2025/main-bot/src/main/java/frc/.clang-format @@ -0,0 +1,6 @@ +Language: Java +BasedOnStyle: Microsoft + +AlignConsecutiveAssignments: Consecutive +AlignConsecutiveDeclarations: Consecutive +ColumnLimit: 0 \ No newline at end of file diff --git a/2024-2025/main-bot/src/main/java/frc/robot/Constants.java b/2024-2025/main-bot/src/main/java/frc/robot/Constants.java new file mode 100644 index 0000000..baac14d --- /dev/null +++ b/2024-2025/main-bot/src/main/java/frc/robot/Constants.java @@ -0,0 +1,120 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot; + +import frc.robot.generated.TunerConstants; +import static edu.wpi.first.units.Units.*; +import edu.wpi.first.units.measure.Angle; + +import edu.wpi.first.units.measure.Distance; + +/** + * 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 class Constants { + public static class OperatorConstants { + public static final int kDriverControllerPort = 0; + public static final int kAuxiliaryControllerPort = 1; + } + + // PLACEHOLDER IDS!!! + public static class ElevatorConstants { + public static final int kElevatorLeftMotorID = 12; + public static final int kElevatorRightMotorID = 13; + public static final double kMotorElevatorSpeed = 0.2; + public static final int kLeftElevatorEncoderID1 = 0; + public static final int kLeftElevatorEncoderID2 = 1; + public static final int kRightElevatorEncoderID1 = 2; + public static final int kRightElevatorEncoderID2 = 3; + public static final int kElevatorEncoderBottomValue = 0; + public static final int kElevatorEncoderTopValue = 1000; + + public static class ElevatorPreset { + // PLACEHOLDER VALUES!!! + public static final double level1EncoderValue = 0.5; + public static final double level2EncoderValue = 1.0; + public static final double level3EncoderValue = 1.5; + public static final double level4EncoderValue = 2.0; + } + } + + public static final class AlgaeArmConstants { + public static final int algaeArmBarMotorID = 8;// placeholder + } + + public static class CoralArmConstants { + public static final int coralArmMotorID = 69;// placeholder with funny number hehe + public static final int kCoralEncoderID1 = 4; + public static final int kCoralEncoderID2 = 5; + public static final int kCoralEncoderTopValue = 1000; + public static final int kCoralEncoderTopBuffer = kCoralEncoderTopValue + 10; + public static final int kCoralEncoderBottomValue = 0; + public static final int kCoralEncoderBottomBuffer = kCoralEncoderBottomValue - 10; + } + + public static class ClimberConstants { + public static final int kLeftClimberMotorID = 25; // TEMP + public static final int kRightClimberMotorID = 26; // TEMP + public static final int kClimberLimitSwitchID = 6; // TEMP + } + + public static class DriveTrainConstants { + public static final double MaxAngularRate = RotationsPerSecond.of(0.75).in(RadiansPerSecond); + public static final double MaxSpeed = TunerConstants.kSpeedAt12Volts.in(MetersPerSecond); + public static final double gearRatio = 4.59375; + public static final double lengthBetweenSwerveModules = 22.5; + public static final double lengthOfBumpers = 25.0; // placeholder + + // Motor and encoder ids (ALL ARE PLACEHOLDERS. FIND ACTUAL IDS IN + // COMMANDSWERVEDRIVETRAIN.JAVA) + public static final int FLDriveMotorID = 0; + public static final int FLTurnMotorID = 1; + // You can finish this out Scott! :D + + // Front Left Constants + public static final int kFrontLeftDriveMotorId = 42; + public static final int kFrontLeftSteerMotorId = 1; + public static final int kFrontLeftEncoderId = 0; + public static final Angle kFrontLeftEncoderOffset = Rotations.of(-0.432373046875); + public static final boolean kFrontLeftSteerMotorInverted = true; + public static final boolean kFrontLeftEncoderInverted = false; + public static final Distance kFrontLeftXPos = Inches.of(11.25); + public static final Distance kFrontLeftYPos = Inches.of(11.25); + // Front Right Constants + public static final int kFrontRightDriveMotorId = 2; + public static final int kFrontRightSteerMotorId = 3; + public static final int kFrontRightEncoderId = 2; + public static final Angle kFrontRightEncoderOffset = Rotations.of(-0.282958984375); + public static final boolean kFrontRightSteerMotorInverted = true; + public static final boolean kFrontRightEncoderInverted = false; + public static final Distance kFrontRightXPos = Inches.of(11.25); + public static final Distance kFrontRightYPos = Inches.of(-11.25); + // Back Left Constants + public static final int kBackLeftDriveMotorId = 6; + public static final int kBackLeftSteerMotorId = 7; + public static final int kBackLeftEncoderId = 6; + public static final Angle kBackLeftEncoderOffset = Rotations.of(-0.09326171875); + public static final boolean kBackLeftSteerMotorInverted = true; + public static final boolean kBackLeftEncoderInverted = false; + public static final Distance kBackLeftXPos = Inches.of(-11.25); + public static final Distance kBackLeftYPos = Inches.of(11.25); + // Back Right Constants + public static final int kBackRightDriveMotorId = 4; + public static final int kBackRightSteerMotorId = 0; + public static final int kBackRightEncoderId = 4; + public static final Angle kBackRightEncoderOffset = Rotations.of(-0.111328125); + public static final boolean kBackRightSteerMotorInverted = true; + public static final boolean kBackRightEncoderInverted = false; + public static final Distance kBackRightXPos = Inches.of(-11.25); + public static final Distance kBackRightYPos = Inches.of(-11.25); + } +} diff --git a/2024-2025/main-bot/src/main/java/frc/robot/LimelightHelpers.java b/2024-2025/main-bot/src/main/java/frc/robot/LimelightHelpers.java new file mode 100644 index 0000000..ddafedd --- /dev/null +++ b/2024-2025/main-bot/src/main/java/frc/robot/LimelightHelpers.java @@ -0,0 +1,1647 @@ +//LimelightHelpers v1.11 (REQUIRES LLOS 2025.0 OR LATER) + +package frc.robot; + +import edu.wpi.first.networktables.DoubleArrayEntry; +import edu.wpi.first.networktables.NetworkTable; +import edu.wpi.first.networktables.NetworkTableEntry; +import edu.wpi.first.networktables.NetworkTableInstance; +import edu.wpi.first.networktables.TimestampedDoubleArray; +import frc.robot.LimelightHelpers.LimelightResults; +import frc.robot.LimelightHelpers.PoseEstimate; +import edu.wpi.first.math.geometry.Pose2d; +import edu.wpi.first.math.geometry.Pose3d; +import edu.wpi.first.math.geometry.Rotation2d; +import edu.wpi.first.math.geometry.Translation3d; +import edu.wpi.first.math.util.Units; +import edu.wpi.first.math.geometry.Rotation3d; +import edu.wpi.first.math.geometry.Translation2d; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonFormat.Shape; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.concurrent.ConcurrentHashMap; + +/** + * LimelightHelpers provides static methods and classes for interfacing with Limelight vision cameras in FRC. + * This library supports all Limelight features including AprilTag tracking, Neural Networks, and standard color/retroreflective tracking. + */ +public class LimelightHelpers { + + private static final Map doubleArrayEntries = new ConcurrentHashMap<>(); + + /** + * Represents a Color/Retroreflective Target Result extracted from JSON Output + */ + public static class LimelightTarget_Retro { + + @JsonProperty("t6c_ts") + private double[] cameraPose_TargetSpace; + + @JsonProperty("t6r_fs") + private double[] robotPose_FieldSpace; + + @JsonProperty("t6r_ts") + private double[] robotPose_TargetSpace; + + @JsonProperty("t6t_cs") + private double[] targetPose_CameraSpace; + + @JsonProperty("t6t_rs") + private double[] targetPose_RobotSpace; + + public Pose3d getCameraPose_TargetSpace() + { + return toPose3D(cameraPose_TargetSpace); + } + public Pose3d getRobotPose_FieldSpace() + { + return toPose3D(robotPose_FieldSpace); + } + public Pose3d getRobotPose_TargetSpace() + { + return toPose3D(robotPose_TargetSpace); + } + public Pose3d getTargetPose_CameraSpace() + { + return toPose3D(targetPose_CameraSpace); + } + public Pose3d getTargetPose_RobotSpace() + { + return toPose3D(targetPose_RobotSpace); + } + + public Pose2d getCameraPose_TargetSpace2D() + { + return toPose2D(cameraPose_TargetSpace); + } + public Pose2d getRobotPose_FieldSpace2D() + { + return toPose2D(robotPose_FieldSpace); + } + public Pose2d getRobotPose_TargetSpace2D() + { + return toPose2D(robotPose_TargetSpace); + } + public Pose2d getTargetPose_CameraSpace2D() + { + return toPose2D(targetPose_CameraSpace); + } + public Pose2d getTargetPose_RobotSpace2D() + { + return toPose2D(targetPose_RobotSpace); + } + + @JsonProperty("ta") + public double ta; + + @JsonProperty("tx") + public double tx; + + @JsonProperty("ty") + public double ty; + + @JsonProperty("txp") + public double tx_pixels; + + @JsonProperty("typ") + public double ty_pixels; + + @JsonProperty("tx_nocross") + public double tx_nocrosshair; + + @JsonProperty("ty_nocross") + public double ty_nocrosshair; + + @JsonProperty("ts") + public double ts; + + public LimelightTarget_Retro() { + cameraPose_TargetSpace = new double[6]; + robotPose_FieldSpace = new double[6]; + robotPose_TargetSpace = new double[6]; + targetPose_CameraSpace = new double[6]; + targetPose_RobotSpace = new double[6]; + } + + } + + /** + * Represents an AprilTag/Fiducial Target Result extracted from JSON Output + */ + public static class LimelightTarget_Fiducial { + + @JsonProperty("fID") + public double fiducialID; + + @JsonProperty("fam") + public String fiducialFamily; + + @JsonProperty("t6c_ts") + private double[] cameraPose_TargetSpace; + + @JsonProperty("t6r_fs") + private double[] robotPose_FieldSpace; + + @JsonProperty("t6r_ts") + private double[] robotPose_TargetSpace; + + @JsonProperty("t6t_cs") + private double[] targetPose_CameraSpace; + + @JsonProperty("t6t_rs") + private double[] targetPose_RobotSpace; + + public Pose3d getCameraPose_TargetSpace() + { + return toPose3D(cameraPose_TargetSpace); + } + public Pose3d getRobotPose_FieldSpace() + { + return toPose3D(robotPose_FieldSpace); + } + public Pose3d getRobotPose_TargetSpace() + { + return toPose3D(robotPose_TargetSpace); + } + public Pose3d getTargetPose_CameraSpace() + { + return toPose3D(targetPose_CameraSpace); + } + public Pose3d getTargetPose_RobotSpace() + { + return toPose3D(targetPose_RobotSpace); + } + + public Pose2d getCameraPose_TargetSpace2D() + { + return toPose2D(cameraPose_TargetSpace); + } + public Pose2d getRobotPose_FieldSpace2D() + { + return toPose2D(robotPose_FieldSpace); + } + public Pose2d getRobotPose_TargetSpace2D() + { + return toPose2D(robotPose_TargetSpace); + } + public Pose2d getTargetPose_CameraSpace2D() + { + return toPose2D(targetPose_CameraSpace); + } + public Pose2d getTargetPose_RobotSpace2D() + { + return toPose2D(targetPose_RobotSpace); + } + + @JsonProperty("ta") + public double ta; + + @JsonProperty("tx") + public double tx; + + @JsonProperty("ty") + public double ty; + + @JsonProperty("txp") + public double tx_pixels; + + @JsonProperty("typ") + public double ty_pixels; + + @JsonProperty("tx_nocross") + public double tx_nocrosshair; + + @JsonProperty("ty_nocross") + public double ty_nocrosshair; + + @JsonProperty("ts") + public double ts; + + public LimelightTarget_Fiducial() { + cameraPose_TargetSpace = new double[6]; + robotPose_FieldSpace = new double[6]; + robotPose_TargetSpace = new double[6]; + targetPose_CameraSpace = new double[6]; + targetPose_RobotSpace = new double[6]; + } + } + + /** + * Represents a Barcode Target Result extracted from JSON Output + */ + public static class LimelightTarget_Barcode { + + /** + * Barcode family type (e.g. "QR", "DataMatrix", etc.) + */ + @JsonProperty("fam") + public String family; + + /** + * Gets the decoded data content of the barcode + */ + @JsonProperty("data") + public String data; + + @JsonProperty("txp") + public double tx_pixels; + + @JsonProperty("typ") + public double ty_pixels; + + @JsonProperty("tx") + public double tx; + + @JsonProperty("ty") + public double ty; + + @JsonProperty("tx_nocross") + public double tx_nocrosshair; + + @JsonProperty("ty_nocross") + public double ty_nocrosshair; + + @JsonProperty("ta") + public double ta; + + @JsonProperty("pts") + public double[][] corners; + + public LimelightTarget_Barcode() { + } + + public String getFamily() { + return family; + } + } + + /** + * Represents a Neural Classifier Pipeline Result extracted from JSON Output + */ + public static class LimelightTarget_Classifier { + + @JsonProperty("class") + public String className; + + @JsonProperty("classID") + public double classID; + + @JsonProperty("conf") + public double confidence; + + @JsonProperty("zone") + public double zone; + + @JsonProperty("tx") + public double tx; + + @JsonProperty("txp") + public double tx_pixels; + + @JsonProperty("ty") + public double ty; + + @JsonProperty("typ") + public double ty_pixels; + + public LimelightTarget_Classifier() { + } + } + + /** + * Represents a Neural Detector Pipeline Result extracted from JSON Output + */ + public static class LimelightTarget_Detector { + + @JsonProperty("class") + public String className; + + @JsonProperty("classID") + public double classID; + + @JsonProperty("conf") + public double confidence; + + @JsonProperty("ta") + public double ta; + + @JsonProperty("tx") + public double tx; + + @JsonProperty("ty") + public double ty; + + @JsonProperty("txp") + public double tx_pixels; + + @JsonProperty("typ") + public double ty_pixels; + + @JsonProperty("tx_nocross") + public double tx_nocrosshair; + + @JsonProperty("ty_nocross") + public double ty_nocrosshair; + + public LimelightTarget_Detector() { + } + } + + /** + * Limelight Results object, parsed from a Limelight's JSON results output. + */ + public static class LimelightResults { + + public String error; + + @JsonProperty("pID") + public double pipelineID; + + @JsonProperty("tl") + public double latency_pipeline; + + @JsonProperty("cl") + public double latency_capture; + + public double latency_jsonParse; + + @JsonProperty("ts") + public double timestamp_LIMELIGHT_publish; + + @JsonProperty("ts_rio") + public double timestamp_RIOFPGA_capture; + + @JsonProperty("v") + @JsonFormat(shape = Shape.NUMBER) + public boolean valid; + + @JsonProperty("botpose") + public double[] botpose; + + @JsonProperty("botpose_wpired") + public double[] botpose_wpired; + + @JsonProperty("botpose_wpiblue") + public double[] botpose_wpiblue; + + @JsonProperty("botpose_tagcount") + public double botpose_tagcount; + + @JsonProperty("botpose_span") + public double botpose_span; + + @JsonProperty("botpose_avgdist") + public double botpose_avgdist; + + @JsonProperty("botpose_avgarea") + public double botpose_avgarea; + + @JsonProperty("t6c_rs") + public double[] camerapose_robotspace; + + public Pose3d getBotPose3d() { + return toPose3D(botpose); + } + + public Pose3d getBotPose3d_wpiRed() { + return toPose3D(botpose_wpired); + } + + public Pose3d getBotPose3d_wpiBlue() { + return toPose3D(botpose_wpiblue); + } + + public Pose2d getBotPose2d() { + return toPose2D(botpose); + } + + public Pose2d getBotPose2d_wpiRed() { + return toPose2D(botpose_wpired); + } + + public Pose2d getBotPose2d_wpiBlue() { + return toPose2D(botpose_wpiblue); + } + + @JsonProperty("Retro") + public LimelightTarget_Retro[] targets_Retro; + + @JsonProperty("Fiducial") + public LimelightTarget_Fiducial[] targets_Fiducials; + + @JsonProperty("Classifier") + public LimelightTarget_Classifier[] targets_Classifier; + + @JsonProperty("Detector") + public LimelightTarget_Detector[] targets_Detector; + + @JsonProperty("Barcode") + public LimelightTarget_Barcode[] targets_Barcode; + + public LimelightResults() { + botpose = new double[6]; + botpose_wpired = new double[6]; + botpose_wpiblue = new double[6]; + camerapose_robotspace = new double[6]; + targets_Retro = new LimelightTarget_Retro[0]; + targets_Fiducials = new LimelightTarget_Fiducial[0]; + targets_Classifier = new LimelightTarget_Classifier[0]; + targets_Detector = new LimelightTarget_Detector[0]; + targets_Barcode = new LimelightTarget_Barcode[0]; + + } + + + } + + /** + * Represents a Limelight Raw Fiducial result from Limelight's NetworkTables output. + */ + public static class RawFiducial { + public int id = 0; + public double txnc = 0; + public double tync = 0; + public double ta = 0; + public double distToCamera = 0; + public double distToRobot = 0; + public double ambiguity = 0; + + + public RawFiducial(int id, double txnc, double tync, double ta, double distToCamera, double distToRobot, double ambiguity) { + this.id = id; + this.txnc = txnc; + this.tync = tync; + this.ta = ta; + this.distToCamera = distToCamera; + this.distToRobot = distToRobot; + this.ambiguity = ambiguity; + } + } + + /** + * Represents a Limelight Raw Neural Detector result from Limelight's NetworkTables output. + */ + public static class RawDetection { + public int classId = 0; + public double txnc = 0; + public double tync = 0; + public double ta = 0; + public double corner0_X = 0; + public double corner0_Y = 0; + public double corner1_X = 0; + public double corner1_Y = 0; + public double corner2_X = 0; + public double corner2_Y = 0; + public double corner3_X = 0; + public double corner3_Y = 0; + + + public RawDetection(int classId, double txnc, double tync, double ta, + double corner0_X, double corner0_Y, + double corner1_X, double corner1_Y, + double corner2_X, double corner2_Y, + double corner3_X, double corner3_Y ) { + this.classId = classId; + this.txnc = txnc; + this.tync = tync; + this.ta = ta; + this.corner0_X = corner0_X; + this.corner0_Y = corner0_Y; + this.corner1_X = corner1_X; + this.corner1_Y = corner1_Y; + this.corner2_X = corner2_X; + this.corner2_Y = corner2_Y; + this.corner3_X = corner3_X; + this.corner3_Y = corner3_Y; + } + } + + /** + * Represents a 3D Pose Estimate. + */ + public static class PoseEstimate { + public Pose2d pose; + public double timestampSeconds; + public double latency; + public int tagCount; + public double tagSpan; + public double avgTagDist; + public double avgTagArea; + + public RawFiducial[] rawFiducials; + public boolean isMegaTag2; + + /** + * Instantiates a PoseEstimate object with default values + */ + public PoseEstimate() { + this.pose = new Pose2d(); + this.timestampSeconds = 0; + this.latency = 0; + this.tagCount = 0; + this.tagSpan = 0; + this.avgTagDist = 0; + this.avgTagArea = 0; + this.rawFiducials = new RawFiducial[]{}; + this.isMegaTag2 = false; + } + + public PoseEstimate(Pose2d pose, double timestampSeconds, double latency, + int tagCount, double tagSpan, double avgTagDist, + double avgTagArea, RawFiducial[] rawFiducials, boolean isMegaTag2) { + + this.pose = pose; + this.timestampSeconds = timestampSeconds; + this.latency = latency; + this.tagCount = tagCount; + this.tagSpan = tagSpan; + this.avgTagDist = avgTagDist; + this.avgTagArea = avgTagArea; + this.rawFiducials = rawFiducials; + this.isMegaTag2 = isMegaTag2; + } + + } + + /** + * Encapsulates the state of an internal Limelight IMU. + */ + public static class IMUData { + public double robotYaw = 0.0; + public double Roll = 0.0; + public double Pitch = 0.0; + public double Yaw = 0.0; + public double gyroX = 0.0; + public double gyroY = 0.0; + public double gyroZ = 0.0; + public double accelX = 0.0; + public double accelY = 0.0; + public double accelZ = 0.0; + + public IMUData() {} + + public IMUData(double[] imuData) { + if (imuData != null && imuData.length >= 10) { + this.robotYaw = imuData[0]; + this.Roll = imuData[1]; + this.Pitch = imuData[2]; + this.Yaw = imuData[3]; + this.gyroX = imuData[4]; + this.gyroY = imuData[5]; + this.gyroZ = imuData[6]; + this.accelX = imuData[7]; + this.accelY = imuData[8]; + this.accelZ = imuData[9]; + } + } + } + + + private static ObjectMapper mapper; + + /** + * Print JSON Parse time to the console in milliseconds + */ + static boolean profileJSON = false; + + static final String sanitizeName(String name) { + if (name == "" || name == null) { + return "limelight"; + } + return name; + } + + /** + * Takes a 6-length array of pose data and converts it to a Pose3d object. + * Array format: [x, y, z, roll, pitch, yaw] where angles are in degrees. + * @param inData Array containing pose data [x, y, z, roll, pitch, yaw] + * @return Pose3d object representing the pose, or empty Pose3d if invalid data + */ + public static Pose3d toPose3D(double[] inData){ + if(inData.length < 6) + { + //System.err.println("Bad LL 3D Pose Data!"); + return new Pose3d(); + } + return new Pose3d( + new Translation3d(inData[0], inData[1], inData[2]), + new Rotation3d(Units.degreesToRadians(inData[3]), Units.degreesToRadians(inData[4]), + Units.degreesToRadians(inData[5]))); + } + + /** + * Takes a 6-length array of pose data and converts it to a Pose2d object. + * Uses only x, y, and yaw components, ignoring z, roll, and pitch. + * Array format: [x, y, z, roll, pitch, yaw] where angles are in degrees. + * @param inData Array containing pose data [x, y, z, roll, pitch, yaw] + * @return Pose2d object representing the pose, or empty Pose2d if invalid data + */ + public static Pose2d toPose2D(double[] inData){ + if(inData.length < 6) + { + //System.err.println("Bad LL 2D Pose Data!"); + return new Pose2d(); + } + Translation2d tran2d = new Translation2d(inData[0], inData[1]); + Rotation2d r2d = new Rotation2d(Units.degreesToRadians(inData[5])); + return new Pose2d(tran2d, r2d); + } + + /** + * Converts a Pose3d object to an array of doubles in the format [x, y, z, roll, pitch, yaw]. + * Translation components are in meters, rotation components are in degrees. + * + * @param pose The Pose3d object to convert + * @return A 6-element array containing [x, y, z, roll, pitch, yaw] + */ + public static double[] pose3dToArray(Pose3d pose) { + double[] result = new double[6]; + result[0] = pose.getTranslation().getX(); + result[1] = pose.getTranslation().getY(); + result[2] = pose.getTranslation().getZ(); + result[3] = Units.radiansToDegrees(pose.getRotation().getX()); + result[4] = Units.radiansToDegrees(pose.getRotation().getY()); + result[5] = Units.radiansToDegrees(pose.getRotation().getZ()); + return result; + } + + /** + * Converts a Pose2d object to an array of doubles in the format [x, y, z, roll, pitch, yaw]. + * Translation components are in meters, rotation components are in degrees. + * Note: z, roll, and pitch will be 0 since Pose2d only contains x, y, and yaw. + * + * @param pose The Pose2d object to convert + * @return A 6-element array containing [x, y, 0, 0, 0, yaw] + */ + public static double[] pose2dToArray(Pose2d pose) { + double[] result = new double[6]; + result[0] = pose.getTranslation().getX(); + result[1] = pose.getTranslation().getY(); + result[2] = 0; + result[3] = Units.radiansToDegrees(0); + result[4] = Units.radiansToDegrees(0); + result[5] = Units.radiansToDegrees(pose.getRotation().getRadians()); + return result; + } + + private static double extractArrayEntry(double[] inData, int position){ + if(inData.length < position+1) + { + return 0; + } + return inData[position]; + } + + private static PoseEstimate getBotPoseEstimate(String limelightName, String entryName, boolean isMegaTag2) { + DoubleArrayEntry poseEntry = LimelightHelpers.getLimelightDoubleArrayEntry(limelightName, entryName); + + TimestampedDoubleArray tsValue = poseEntry.getAtomic(); + double[] poseArray = tsValue.value; + long timestamp = tsValue.timestamp; + + if (poseArray.length == 0) { + // Handle the case where no data is available + return null; // or some default PoseEstimate + } + + var pose = toPose2D(poseArray); + double latency = extractArrayEntry(poseArray, 6); + int tagCount = (int)extractArrayEntry(poseArray, 7); + double tagSpan = extractArrayEntry(poseArray, 8); + double tagDist = extractArrayEntry(poseArray, 9); + double tagArea = extractArrayEntry(poseArray, 10); + + // Convert server timestamp from microseconds to seconds and adjust for latency + double adjustedTimestamp = (timestamp / 1000000.0) - (latency / 1000.0); + + RawFiducial[] rawFiducials = new RawFiducial[tagCount]; + int valsPerFiducial = 7; + int expectedTotalVals = 11 + valsPerFiducial * tagCount; + + if (poseArray.length != expectedTotalVals) { + // Don't populate fiducials + } else { + for(int i = 0; i < tagCount; i++) { + int baseIndex = 11 + (i * valsPerFiducial); + int id = (int)poseArray[baseIndex]; + double txnc = poseArray[baseIndex + 1]; + double tync = poseArray[baseIndex + 2]; + double ta = poseArray[baseIndex + 3]; + double distToCamera = poseArray[baseIndex + 4]; + double distToRobot = poseArray[baseIndex + 5]; + double ambiguity = poseArray[baseIndex + 6]; + rawFiducials[i] = new RawFiducial(id, txnc, tync, ta, distToCamera, distToRobot, ambiguity); + } + } + + return new PoseEstimate(pose, adjustedTimestamp, latency, tagCount, tagSpan, tagDist, tagArea, rawFiducials, isMegaTag2); + } + + /** + * Gets the latest raw fiducial/AprilTag detection results from NetworkTables. + * + * @param limelightName Name/identifier of the Limelight + * @return Array of RawFiducial objects containing detection details + */ + public static RawFiducial[] getRawFiducials(String limelightName) { + var entry = LimelightHelpers.getLimelightNTTableEntry(limelightName, "rawfiducials"); + var rawFiducialArray = entry.getDoubleArray(new double[0]); + int valsPerEntry = 7; + if (rawFiducialArray.length % valsPerEntry != 0) { + return new RawFiducial[0]; + } + + int numFiducials = rawFiducialArray.length / valsPerEntry; + RawFiducial[] rawFiducials = new RawFiducial[numFiducials]; + + for (int i = 0; i < numFiducials; i++) { + int baseIndex = i * valsPerEntry; + int id = (int) extractArrayEntry(rawFiducialArray, baseIndex); + double txnc = extractArrayEntry(rawFiducialArray, baseIndex + 1); + double tync = extractArrayEntry(rawFiducialArray, baseIndex + 2); + double ta = extractArrayEntry(rawFiducialArray, baseIndex + 3); + double distToCamera = extractArrayEntry(rawFiducialArray, baseIndex + 4); + double distToRobot = extractArrayEntry(rawFiducialArray, baseIndex + 5); + double ambiguity = extractArrayEntry(rawFiducialArray, baseIndex + 6); + + rawFiducials[i] = new RawFiducial(id, txnc, tync, ta, distToCamera, distToRobot, ambiguity); + } + + return rawFiducials; + } + + /** + * Gets the latest raw neural detector results from NetworkTables + * + * @param limelightName Name/identifier of the Limelight + * @return Array of RawDetection objects containing detection details + */ + public static RawDetection[] getRawDetections(String limelightName) { + var entry = LimelightHelpers.getLimelightNTTableEntry(limelightName, "rawdetections"); + var rawDetectionArray = entry.getDoubleArray(new double[0]); + int valsPerEntry = 12; + if (rawDetectionArray.length % valsPerEntry != 0) { + return new RawDetection[0]; + } + + int numDetections = rawDetectionArray.length / valsPerEntry; + RawDetection[] rawDetections = new RawDetection[numDetections]; + + for (int i = 0; i < numDetections; i++) { + int baseIndex = i * valsPerEntry; // Starting index for this detection's data + int classId = (int) extractArrayEntry(rawDetectionArray, baseIndex); + double txnc = extractArrayEntry(rawDetectionArray, baseIndex + 1); + double tync = extractArrayEntry(rawDetectionArray, baseIndex + 2); + double ta = extractArrayEntry(rawDetectionArray, baseIndex + 3); + double corner0_X = extractArrayEntry(rawDetectionArray, baseIndex + 4); + double corner0_Y = extractArrayEntry(rawDetectionArray, baseIndex + 5); + double corner1_X = extractArrayEntry(rawDetectionArray, baseIndex + 6); + double corner1_Y = extractArrayEntry(rawDetectionArray, baseIndex + 7); + double corner2_X = extractArrayEntry(rawDetectionArray, baseIndex + 8); + double corner2_Y = extractArrayEntry(rawDetectionArray, baseIndex + 9); + double corner3_X = extractArrayEntry(rawDetectionArray, baseIndex + 10); + double corner3_Y = extractArrayEntry(rawDetectionArray, baseIndex + 11); + + rawDetections[i] = new RawDetection(classId, txnc, tync, ta, corner0_X, corner0_Y, corner1_X, corner1_Y, corner2_X, corner2_Y, corner3_X, corner3_Y); + } + + return rawDetections; + } + + /** + * Prints detailed information about a PoseEstimate to standard output. + * Includes timestamp, latency, tag count, tag span, average tag distance, + * average tag area, and detailed information about each detected fiducial. + * + * @param pose The PoseEstimate object to print. If null, prints "No PoseEstimate available." + */ + public static void printPoseEstimate(PoseEstimate pose) { + if (pose == null) { + System.out.println("No PoseEstimate available."); + return; + } + + System.out.printf("Pose Estimate Information:%n"); + System.out.printf("Timestamp (Seconds): %.3f%n", pose.timestampSeconds); + System.out.printf("Latency: %.3f ms%n", pose.latency); + System.out.printf("Tag Count: %d%n", pose.tagCount); + System.out.printf("Tag Span: %.2f meters%n", pose.tagSpan); + System.out.printf("Average Tag Distance: %.2f meters%n", pose.avgTagDist); + System.out.printf("Average Tag Area: %.2f%% of image%n", pose.avgTagArea); + System.out.printf("Is MegaTag2: %b%n", pose.isMegaTag2); + System.out.println(); + + if (pose.rawFiducials == null || pose.rawFiducials.length == 0) { + System.out.println("No RawFiducials data available."); + return; + } + + System.out.println("Raw Fiducials Details:"); + for (int i = 0; i < pose.rawFiducials.length; i++) { + RawFiducial fiducial = pose.rawFiducials[i]; + System.out.printf(" Fiducial #%d:%n", i + 1); + System.out.printf(" ID: %d%n", fiducial.id); + System.out.printf(" TXNC: %.2f%n", fiducial.txnc); + System.out.printf(" TYNC: %.2f%n", fiducial.tync); + System.out.printf(" TA: %.2f%n", fiducial.ta); + System.out.printf(" Distance to Camera: %.2f meters%n", fiducial.distToCamera); + System.out.printf(" Distance to Robot: %.2f meters%n", fiducial.distToRobot); + System.out.printf(" Ambiguity: %.2f%n", fiducial.ambiguity); + System.out.println(); + } + } + + public static Boolean validPoseEstimate(PoseEstimate pose) { + return pose != null && pose.rawFiducials != null && pose.rawFiducials.length != 0; + } + + public static NetworkTable getLimelightNTTable(String tableName) { + return NetworkTableInstance.getDefault().getTable(sanitizeName(tableName)); + } + + public static void Flush() { + NetworkTableInstance.getDefault().flush(); + } + + public static NetworkTableEntry getLimelightNTTableEntry(String tableName, String entryName) { + return getLimelightNTTable(tableName).getEntry(entryName); + } + + public static DoubleArrayEntry getLimelightDoubleArrayEntry(String tableName, String entryName) { + String key = tableName + "/" + entryName; + return doubleArrayEntries.computeIfAbsent(key, k -> { + NetworkTable table = getLimelightNTTable(tableName); + return table.getDoubleArrayTopic(entryName).getEntry(new double[0]); + }); + } + + public static double getLimelightNTDouble(String tableName, String entryName) { + return getLimelightNTTableEntry(tableName, entryName).getDouble(0.0); + } + + public static void setLimelightNTDouble(String tableName, String entryName, double val) { + getLimelightNTTableEntry(tableName, entryName).setDouble(val); + } + + public static void setLimelightNTDoubleArray(String tableName, String entryName, double[] val) { + getLimelightNTTableEntry(tableName, entryName).setDoubleArray(val); + } + + public static double[] getLimelightNTDoubleArray(String tableName, String entryName) { + return getLimelightNTTableEntry(tableName, entryName).getDoubleArray(new double[0]); + } + + + public static String getLimelightNTString(String tableName, String entryName) { + return getLimelightNTTableEntry(tableName, entryName).getString(""); + } + + public static String[] getLimelightNTStringArray(String tableName, String entryName) { + return getLimelightNTTableEntry(tableName, entryName).getStringArray(new String[0]); + } + + + public static URL getLimelightURLString(String tableName, String request) { + String urlString = "http://" + sanitizeName(tableName) + ".local:5807/" + request; + URL url; + try { + url = new URL(urlString); + return url; + } catch (MalformedURLException e) { + System.err.println("bad LL URL"); + } + return null; + } + ///// + ///// + + /** + * Does the Limelight have a valid target? + * @param limelightName Name of the Limelight camera ("" for default) + * @return True if a valid target is present, false otherwise + */ + public static boolean getTV(String limelightName) { + return 1.0 == getLimelightNTDouble(limelightName, "tv"); + } + + /** + * Gets the horizontal offset from the crosshair to the target in degrees. + * @param limelightName Name of the Limelight camera ("" for default) + * @return Horizontal offset angle in degrees + */ + public static double getTX(String limelightName) { + return getLimelightNTDouble(limelightName, "tx"); + } + + /** + * Gets the vertical offset from the crosshair to the target in degrees. + * @param limelightName Name of the Limelight camera ("" for default) + * @return Vertical offset angle in degrees + */ + public static double getTY(String limelightName) { + return getLimelightNTDouble(limelightName, "ty"); + } + + /** + * Gets the horizontal offset from the principal pixel/point to the target in degrees. This is the most accurate 2d metric if you are using a calibrated camera and you don't need adjustable crosshair functionality. + * @param limelightName Name of the Limelight camera ("" for default) + * @return Horizontal offset angle in degrees + */ + public static double getTXNC(String limelightName) { + return getLimelightNTDouble(limelightName, "txnc"); + } + + /** + * Gets the vertical offset from the principal pixel/point to the target in degrees. This is the most accurate 2d metric if you are using a calibrated camera and you don't need adjustable crosshair functionality. + * @param limelightName Name of the Limelight camera ("" for default) + * @return Vertical offset angle in degrees + */ + public static double getTYNC(String limelightName) { + return getLimelightNTDouble(limelightName, "tync"); + } + + /** + * Gets the target area as a percentage of the image (0-100%). + * @param limelightName Name of the Limelight camera ("" for default) + * @return Target area percentage (0-100) + */ + public static double getTA(String limelightName) { + return getLimelightNTDouble(limelightName, "ta"); + } + + /** + * T2D is an array that contains several targeting metrcis + * @param limelightName Name of the Limelight camera + * @return Array containing [targetValid, targetCount, targetLatency, captureLatency, tx, ty, txnc, tync, ta, tid, targetClassIndexDetector, + * targetClassIndexClassifier, targetLongSidePixels, targetShortSidePixels, targetHorizontalExtentPixels, targetVerticalExtentPixels, targetSkewDegrees] + */ + public static double[] getT2DArray(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "t2d"); + } + + /** + * Gets the number of targets currently detected. + * @param limelightName Name of the Limelight camera + * @return Number of detected targets + */ + public static int getTargetCount(String limelightName) { + double[] t2d = getT2DArray(limelightName); + if(t2d.length == 17) + { + return (int)t2d[1]; + } + return 0; + } + + /** + * Gets the classifier class index from the currently running neural classifier pipeline + * @param limelightName Name of the Limelight camera + * @return Class index from classifier pipeline + */ + public static int getClassifierClassIndex (String limelightName) { + double[] t2d = getT2DArray(limelightName); + if(t2d.length == 17) + { + return (int)t2d[10]; + } + return 0; + } + + /** + * Gets the detector class index from the primary result of the currently running neural detector pipeline. + * @param limelightName Name of the Limelight camera + * @return Class index from detector pipeline + */ + public static int getDetectorClassIndex (String limelightName) { + double[] t2d = getT2DArray(limelightName); + if(t2d.length == 17) + { + return (int)t2d[11]; + } + return 0; + } + + /** + * Gets the current neural classifier result class name. + * @param limelightName Name of the Limelight camera + * @return Class name string from classifier pipeline + */ + public static String getClassifierClass (String limelightName) { + return getLimelightNTString(limelightName, "tcclass"); + } + + /** + * Gets the primary neural detector result class name. + * @param limelightName Name of the Limelight camera + * @return Class name string from detector pipeline + */ + public static String getDetectorClass (String limelightName) { + return getLimelightNTString(limelightName, "tdclass"); + } + + /** + * Gets the pipeline's processing latency contribution. + * @param limelightName Name of the Limelight camera + * @return Pipeline latency in milliseconds + */ + public static double getLatency_Pipeline(String limelightName) { + return getLimelightNTDouble(limelightName, "tl"); + } + + /** + * Gets the capture latency. + * @param limelightName Name of the Limelight camera + * @return Capture latency in milliseconds + */ + public static double getLatency_Capture(String limelightName) { + return getLimelightNTDouble(limelightName, "cl"); + } + + /** + * Gets the active pipeline index. + * @param limelightName Name of the Limelight camera + * @return Current pipeline index (0-9) + */ + public static double getCurrentPipelineIndex(String limelightName) { + return getLimelightNTDouble(limelightName, "getpipe"); + } + + /** + * Gets the current pipeline type. + * @param limelightName Name of the Limelight camera + * @return Pipeline type string (e.g. "retro", "apriltag", etc) + */ + public static String getCurrentPipelineType(String limelightName) { + return getLimelightNTString(limelightName, "getpipetype"); + } + + /** + * Gets the full JSON results dump. + * @param limelightName Name of the Limelight camera + * @return JSON string containing all current results + */ + public static String getJSONDump(String limelightName) { + return getLimelightNTString(limelightName, "json"); + } + + /** + * Switch to getBotPose + * + * @param limelightName + * @return + */ + @Deprecated + public static double[] getBotpose(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "botpose"); + } + + /** + * Switch to getBotPose_wpiRed + * + * @param limelightName + * @return + */ + @Deprecated + public static double[] getBotpose_wpiRed(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "botpose_wpired"); + } + + /** + * Switch to getBotPose_wpiBlue + * + * @param limelightName + * @return + */ + @Deprecated + public static double[] getBotpose_wpiBlue(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "botpose_wpiblue"); + } + + public static double[] getBotPose(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "botpose"); + } + + public static double[] getBotPose_wpiRed(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "botpose_wpired"); + } + + public static double[] getBotPose_wpiBlue(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "botpose_wpiblue"); + } + + public static double[] getBotPose_TargetSpace(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "botpose_targetspace"); + } + + public static double[] getCameraPose_TargetSpace(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "camerapose_targetspace"); + } + + public static double[] getTargetPose_CameraSpace(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "targetpose_cameraspace"); + } + + public static double[] getTargetPose_RobotSpace(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "targetpose_robotspace"); + } + + public static double[] getTargetColor(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "tc"); + } + + public static double getFiducialID(String limelightName) { + return getLimelightNTDouble(limelightName, "tid"); + } + + public static String getNeuralClassID(String limelightName) { + return getLimelightNTString(limelightName, "tclass"); + } + + public static String[] getRawBarcodeData(String limelightName) { + return getLimelightNTStringArray(limelightName, "rawbarcodes"); + } + + ///// + ///// + + public static Pose3d getBotPose3d(String limelightName) { + double[] poseArray = getLimelightNTDoubleArray(limelightName, "botpose"); + return toPose3D(poseArray); + } + + /** + * (Not Recommended) Gets the robot's 3D pose in the WPILib Red Alliance Coordinate System. + * @param limelightName Name/identifier of the Limelight + * @return Pose3d object representing the robot's position and orientation in Red Alliance field space + */ + public static Pose3d getBotPose3d_wpiRed(String limelightName) { + double[] poseArray = getLimelightNTDoubleArray(limelightName, "botpose_wpired"); + return toPose3D(poseArray); + } + + /** + * (Recommended) Gets the robot's 3D pose in the WPILib Blue Alliance Coordinate System. + * @param limelightName Name/identifier of the Limelight + * @return Pose3d object representing the robot's position and orientation in Blue Alliance field space + */ + public static Pose3d getBotPose3d_wpiBlue(String limelightName) { + double[] poseArray = getLimelightNTDoubleArray(limelightName, "botpose_wpiblue"); + return toPose3D(poseArray); + } + + /** + * Gets the robot's 3D pose with respect to the currently tracked target's coordinate system. + * @param limelightName Name/identifier of the Limelight + * @return Pose3d object representing the robot's position and orientation relative to the target + */ + public static Pose3d getBotPose3d_TargetSpace(String limelightName) { + double[] poseArray = getLimelightNTDoubleArray(limelightName, "botpose_targetspace"); + return toPose3D(poseArray); + } + + /** + * Gets the camera's 3D pose with respect to the currently tracked target's coordinate system. + * @param limelightName Name/identifier of the Limelight + * @return Pose3d object representing the camera's position and orientation relative to the target + */ + public static Pose3d getCameraPose3d_TargetSpace(String limelightName) { + double[] poseArray = getLimelightNTDoubleArray(limelightName, "camerapose_targetspace"); + return toPose3D(poseArray); + } + + /** + * Gets the target's 3D pose with respect to the camera's coordinate system. + * @param limelightName Name/identifier of the Limelight + * @return Pose3d object representing the target's position and orientation relative to the camera + */ + public static Pose3d getTargetPose3d_CameraSpace(String limelightName) { + double[] poseArray = getLimelightNTDoubleArray(limelightName, "targetpose_cameraspace"); + return toPose3D(poseArray); + } + + /** + * Gets the target's 3D pose with respect to the robot's coordinate system. + * @param limelightName Name/identifier of the Limelight + * @return Pose3d object representing the target's position and orientation relative to the robot + */ + public static Pose3d getTargetPose3d_RobotSpace(String limelightName) { + double[] poseArray = getLimelightNTDoubleArray(limelightName, "targetpose_robotspace"); + return toPose3D(poseArray); + } + + /** + * Gets the camera's 3D pose with respect to the robot's coordinate system. + * @param limelightName Name/identifier of the Limelight + * @return Pose3d object representing the camera's position and orientation relative to the robot + */ + public static Pose3d getCameraPose3d_RobotSpace(String limelightName) { + double[] poseArray = getLimelightNTDoubleArray(limelightName, "camerapose_robotspace"); + return toPose3D(poseArray); + } + + /** + * Gets the Pose2d for easy use with Odometry vision pose estimator + * (addVisionMeasurement) + * + * @param limelightName + * @return + */ + public static Pose2d getBotPose2d_wpiBlue(String limelightName) { + + double[] result = getBotPose_wpiBlue(limelightName); + return toPose2D(result); + } + + /** + * Gets the MegaTag1 Pose2d and timestamp for use with WPILib pose estimator (addVisionMeasurement) in the WPILib Blue alliance coordinate system. + * + * @param limelightName + * @return + */ + public static PoseEstimate getBotPoseEstimate_wpiBlue(String limelightName) { + return getBotPoseEstimate(limelightName, "botpose_wpiblue", false); + } + + /** + * Gets the MegaTag2 Pose2d and timestamp for use with WPILib pose estimator (addVisionMeasurement) in the WPILib Blue alliance coordinate system. + * Make sure you are calling setRobotOrientation() before calling this method. + * + * @param limelightName + * @return + */ + public static PoseEstimate getBotPoseEstimate_wpiBlue_MegaTag2(String limelightName) { + return getBotPoseEstimate(limelightName, "botpose_orb_wpiblue", true); + } + + /** + * Gets the Pose2d for easy use with Odometry vision pose estimator + * (addVisionMeasurement) + * + * @param limelightName + * @return + */ + public static Pose2d getBotPose2d_wpiRed(String limelightName) { + + double[] result = getBotPose_wpiRed(limelightName); + return toPose2D(result); + + } + + /** + * Gets the Pose2d and timestamp for use with WPILib pose estimator (addVisionMeasurement) when you are on the RED + * alliance + * @param limelightName + * @return + */ + public static PoseEstimate getBotPoseEstimate_wpiRed(String limelightName) { + return getBotPoseEstimate(limelightName, "botpose_wpired", false); + } + + /** + * Gets the Pose2d and timestamp for use with WPILib pose estimator (addVisionMeasurement) when you are on the RED + * alliance + * @param limelightName + * @return + */ + public static PoseEstimate getBotPoseEstimate_wpiRed_MegaTag2(String limelightName) { + return getBotPoseEstimate(limelightName, "botpose_orb_wpired", true); + } + + /** + * Gets the Pose2d for easy use with Odometry vision pose estimator + * (addVisionMeasurement) + * + * @param limelightName + * @return + */ + public static Pose2d getBotPose2d(String limelightName) { + + double[] result = getBotPose(limelightName); + return toPose2D(result); + + } + + /** + * Gets the current IMU data from NetworkTables. + * IMU data is formatted as [robotYaw, Roll, Pitch, Yaw, gyroX, gyroY, gyroZ, accelX, accelY, accelZ]. + * Returns all zeros if data is invalid or unavailable. + * + * @param limelightName Name/identifier of the Limelight + * @return IMUData object containing all current IMU data + */ + public static IMUData getIMUData(String limelightName) { + double[] imuData = getLimelightNTDoubleArray(limelightName, "imu"); + if (imuData == null || imuData.length < 10) { + return new IMUData(); // Returns object with all zeros + } + return new IMUData(imuData); + } + + ///// + ///// + + public static void setPipelineIndex(String limelightName, int pipelineIndex) { + setLimelightNTDouble(limelightName, "pipeline", pipelineIndex); + } + + + public static void setPriorityTagID(String limelightName, int ID) { + setLimelightNTDouble(limelightName, "priorityid", ID); + } + + /** + * Sets LED mode to be controlled by the current pipeline. + * @param limelightName Name of the Limelight camera + */ + public static void setLEDMode_PipelineControl(String limelightName) { + setLimelightNTDouble(limelightName, "ledMode", 0); + } + + public static void setLEDMode_ForceOff(String limelightName) { + setLimelightNTDouble(limelightName, "ledMode", 1); + } + + public static void setLEDMode_ForceBlink(String limelightName) { + setLimelightNTDouble(limelightName, "ledMode", 2); + } + + public static void setLEDMode_ForceOn(String limelightName) { + setLimelightNTDouble(limelightName, "ledMode", 3); + } + + /** + * Enables standard side-by-side stream mode. + * @param limelightName Name of the Limelight camera + */ + public static void setStreamMode_Standard(String limelightName) { + setLimelightNTDouble(limelightName, "stream", 0); + } + + /** + * Enables Picture-in-Picture mode with secondary stream in the corner. + * @param limelightName Name of the Limelight camera + */ + public static void setStreamMode_PiPMain(String limelightName) { + setLimelightNTDouble(limelightName, "stream", 1); + } + + /** + * Enables Picture-in-Picture mode with primary stream in the corner. + * @param limelightName Name of the Limelight camera + */ + public static void setStreamMode_PiPSecondary(String limelightName) { + setLimelightNTDouble(limelightName, "stream", 2); + } + + + /** + * Sets the crop window for the camera. The crop window in the UI must be completely open. + * @param limelightName Name of the Limelight camera + * @param cropXMin Minimum X value (-1 to 1) + * @param cropXMax Maximum X value (-1 to 1) + * @param cropYMin Minimum Y value (-1 to 1) + * @param cropYMax Maximum Y value (-1 to 1) + */ + public static void setCropWindow(String limelightName, double cropXMin, double cropXMax, double cropYMin, double cropYMax) { + double[] entries = new double[4]; + entries[0] = cropXMin; + entries[1] = cropXMax; + entries[2] = cropYMin; + entries[3] = cropYMax; + setLimelightNTDoubleArray(limelightName, "crop", entries); + } + + /** + * Sets 3D offset point for easy 3D targeting. + */ + public static void setFiducial3DOffset(String limelightName, double offsetX, double offsetY, double offsetZ) { + double[] entries = new double[3]; + entries[0] = offsetX; + entries[1] = offsetY; + entries[2] = offsetZ; + setLimelightNTDoubleArray(limelightName, "fiducial_offset_set", entries); + } + + /** + * Sets robot orientation values used by MegaTag2 localization algorithm. + * + * @param limelightName Name/identifier of the Limelight + * @param yaw Robot yaw in degrees. 0 = robot facing red alliance wall in FRC + * @param yawRate (Unnecessary) Angular velocity of robot yaw in degrees per second + * @param pitch (Unnecessary) Robot pitch in degrees + * @param pitchRate (Unnecessary) Angular velocity of robot pitch in degrees per second + * @param roll (Unnecessary) Robot roll in degrees + * @param rollRate (Unnecessary) Angular velocity of robot roll in degrees per second + */ + public static void SetRobotOrientation(String limelightName, double yaw, double yawRate, + double pitch, double pitchRate, + double roll, double rollRate) { + SetRobotOrientation_INTERNAL(limelightName, yaw, yawRate, pitch, pitchRate, roll, rollRate, true); + } + + public static void SetRobotOrientation_NoFlush(String limelightName, double yaw, double yawRate, + double pitch, double pitchRate, + double roll, double rollRate) { + SetRobotOrientation_INTERNAL(limelightName, yaw, yawRate, pitch, pitchRate, roll, rollRate, false); + } + + private static void SetRobotOrientation_INTERNAL(String limelightName, double yaw, double yawRate, + double pitch, double pitchRate, + double roll, double rollRate, boolean flush) { + + double[] entries = new double[6]; + entries[0] = yaw; + entries[1] = yawRate; + entries[2] = pitch; + entries[3] = pitchRate; + entries[4] = roll; + entries[5] = rollRate; + setLimelightNTDoubleArray(limelightName, "robot_orientation_set", entries); + if(flush) + { + Flush(); + } + } + + /** + * Configures the IMU mode for MegaTag2 Localization + * + * @param limelightName Name/identifier of the Limelight + * @param mode IMU mode. + */ + public static void SetIMUMode(String limelightName, int mode) { + setLimelightNTDouble(limelightName, "imumode_set", mode); + } + + /** + * Sets the 3D point-of-interest offset for the current fiducial pipeline. + * https://docs.limelightvision.io/docs/docs-limelight/pipeline-apriltag/apriltag-3d#point-of-interest-tracking + * + * @param limelightName Name/identifier of the Limelight + * @param x X offset in meters + * @param y Y offset in meters + * @param z Z offset in meters + */ + public static void SetFidcuial3DOffset(String limelightName, double x, double y, + double z) { + + double[] entries = new double[3]; + entries[0] = x; + entries[1] = y; + entries[2] = z; + setLimelightNTDoubleArray(limelightName, "fiducial_offset_set", entries); + } + + /** + * Overrides the valid AprilTag IDs that will be used for localization. + * Tags not in this list will be ignored for robot pose estimation. + * + * @param limelightName Name/identifier of the Limelight + * @param validIDs Array of valid AprilTag IDs to track + */ + public static void SetFiducialIDFiltersOverride(String limelightName, int[] validIDs) { + double[] validIDsDouble = new double[validIDs.length]; + for (int i = 0; i < validIDs.length; i++) { + validIDsDouble[i] = validIDs[i]; + } + setLimelightNTDoubleArray(limelightName, "fiducial_id_filters_set", validIDsDouble); + } + + /** + * Sets the downscaling factor for AprilTag detection. + * Increasing downscale can improve performance at the cost of potentially reduced detection range. + * + * @param limelightName Name/identifier of the Limelight + * @param downscale Downscale factor. Valid values: 1.0 (no downscale), 1.5, 2.0, 3.0, 4.0. Set to 0 for pipeline control. + */ + public static void SetFiducialDownscalingOverride(String limelightName, float downscale) + { + int d = 0; // pipeline + if (downscale == 1.0) + { + d = 1; + } + if (downscale == 1.5) + { + d = 2; + } + if (downscale == 2) + { + d = 3; + } + if (downscale == 3) + { + d = 4; + } + if (downscale == 4) + { + d = 5; + } + setLimelightNTDouble(limelightName, "fiducial_downscale_set", d); + } + + /** + * Sets the camera pose relative to the robot. + * @param limelightName Name of the Limelight camera + * @param forward Forward offset in meters + * @param side Side offset in meters + * @param up Up offset in meters + * @param roll Roll angle in degrees + * @param pitch Pitch angle in degrees + * @param yaw Yaw angle in degrees + */ + public static void setCameraPose_RobotSpace(String limelightName, double forward, double side, double up, double roll, double pitch, double yaw) { + double[] entries = new double[6]; + entries[0] = forward; + entries[1] = side; + entries[2] = up; + entries[3] = roll; + entries[4] = pitch; + entries[5] = yaw; + setLimelightNTDoubleArray(limelightName, "camerapose_robotspace_set", entries); + } + + ///// + ///// + + public static void setPythonScriptData(String limelightName, double[] outgoingPythonData) { + setLimelightNTDoubleArray(limelightName, "llrobot", outgoingPythonData); + } + + public static double[] getPythonScriptData(String limelightName) { + return getLimelightNTDoubleArray(limelightName, "llpython"); + } + + ///// + ///// + + /** + * Asynchronously take snapshot. + */ + public static CompletableFuture takeSnapshot(String tableName, String snapshotName) { + return CompletableFuture.supplyAsync(() -> { + return SYNCH_TAKESNAPSHOT(tableName, snapshotName); + }); + } + + private static boolean SYNCH_TAKESNAPSHOT(String tableName, String snapshotName) { + URL url = getLimelightURLString(tableName, "capturesnapshot"); + try { + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + if (snapshotName != null && snapshotName != "") { + connection.setRequestProperty("snapname", snapshotName); + } + + int responseCode = connection.getResponseCode(); + if (responseCode == 200) { + return true; + } else { + System.err.println("Bad LL Request"); + } + } catch (IOException e) { + System.err.println(e.getMessage()); + } + return false; + } + + /** + * Gets the latest JSON results output and returns a LimelightResults object. + * @param limelightName Name of the Limelight camera + * @return LimelightResults object containing all current target data + */ + public static LimelightResults getLatestResults(String limelightName) { + + long start = System.nanoTime(); + LimelightHelpers.LimelightResults results = new LimelightHelpers.LimelightResults(); + if (mapper == null) { + mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } + + try { + results = mapper.readValue(getJSONDump(limelightName), LimelightResults.class); + } catch (JsonProcessingException e) { + results.error = "lljson error: " + e.getMessage(); + } + + long end = System.nanoTime(); + double millis = (end - start) * .000001; + results.latency_jsonParse = millis; + if (profileJSON) { + System.out.printf("lljson: %.2f\r\n", millis); + } + + return results; + } +} \ No newline at end of file diff --git a/2024-2025/main-bot/src/main/java/frc/robot/Logging.java b/2024-2025/main-bot/src/main/java/frc/robot/Logging.java new file mode 100644 index 0000000..6090b5a --- /dev/null +++ b/2024-2025/main-bot/src/main/java/frc/robot/Logging.java @@ -0,0 +1,32 @@ +package frc.robot; + +import java.lang.Math; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; + +public class Logging { + String Name; + boolean isError; + + public Logging(String name) { + Name = name; + } + + public void log(String message) { + System.out.println(Name + ": " + message); + } + + public void error(String errorMessage) { + isError = true; + try { + throw new Error("Error:" + Name + ": " + errorMessage); + } catch (Error e) { + // This does the error thing + SmartDashboard.putBoolean(Name + ".Error", true); + } + } + + public void fixError() { + isError = false; + SmartDashboard.putBoolean(Name + ".Error", false); + } +} \ No newline at end of file diff --git a/2024-2025/main-bot/src/main/java/frc/robot/Main.java b/2024-2025/main-bot/src/main/java/frc/robot/Main.java new file mode 100644 index 0000000..6631d14 --- /dev/null +++ b/2024-2025/main-bot/src/main/java/frc/robot/Main.java @@ -0,0 +1,26 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package 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. + * Man it sure is nice to add secret comments for others to find as easter eggs :O + */ + public static void main(String[] args) { + RobotBase.startRobot(Robot::new); + } +} diff --git a/2024-2025/main-bot/src/main/java/frc/robot/Robot.java b/2024-2025/main-bot/src/main/java/frc/robot/Robot.java new file mode 100644 index 0000000..9a5e699 --- /dev/null +++ b/2024-2025/main-bot/src/main/java/frc/robot/Robot.java @@ -0,0 +1,143 @@ +// PROGRAMMING TO DOS! + +// Basic TO DOs +// Set up Elevator simulation or Algae arm simulation in test bed // Status: Failed + +// Advanced TO DOs +//NONE + +// To-Dos: Once the elevator is attached +// Move elevator and update encoder preset values in Constants.java // Status: Not Started +// Check which motors need to be reversed// Status: Not Started +// Investigate Motion Magic // Status: Not Started + +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot; + +import org.ironmaple.simulation.SimulatedArena; +import org.ironmaple.simulation.seasonspecific.reefscape2025.ReefscapeAlgaeOnField; + +import com.ctre.phoenix6.SignalLogger; + +import edu.wpi.first.wpilibj.TimedRobot; + +import edu.wpi.first.wpilibj2.command.Command; + +import edu.wpi.first.wpilibj2.command.CommandScheduler; + +/** + * The methods in this class are called automatically 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 Main.java file in the project. + */ +public class Robot extends TimedRobot { + + private Command m_autonomousCommand; + + private final RobotContainer m_robotContainer; + + /** + * This function is run when the robot is first started up and should be used + * for any initialization code. + */ + public Robot() {// instantiate robot container + + m_robotContainer = new RobotContainer(); + + } + + /** + * This function is called every 20 ms, no matter the mode. Use this for items + * like diagnostics that you want ran during disabled, autonomous, teleoperated + * and test. + * + *

+ * This runs after the mode specific periodic functions, but before LiveWindow + * and SmartDashboard integrated updating. + */ + @Override + public void robotPeriodic() { + // Runs the Scheduler. This is responsible for polling buttons, adding + // newly-scheduled + // commands, running already-scheduled commands, removing finished or + // interrupted commands, + // and running subsystem periodic() methods. This must be called from the + // robot's periodic + // block in order for anything in the Command-based framework to work. + CommandScheduler.getInstance().run(); + } + + /** This function is called once each time the robot enters Disabled mode. */ + @Override + public void disabledInit() { + SignalLogger.stop(); + } + + @Override + public void disabledPeriodic() { + } + + /** + * This autonomous runs the autonomous command selected by your + * {@link RobotContainer} class. + */ + @Override + public void autonomousInit() { + m_autonomousCommand = m_robotContainer.getAutonomousCommand(); + + // schedule the autonomous command (example) + if (m_autonomousCommand != null) { + m_autonomousCommand.schedule(); + } + } + + /** This function is called periodically during autonomous. */ + @Override + public void autonomousPeriodic() { + } + + @Override + public void teleopInit() { + // This makes sure that the autonomous stops running when + // teleop starts running. If you want the autonomous to + // continue until interrupted by another command, remove + // this line or comment it out. + if (m_autonomousCommand != null) { + m_autonomousCommand.cancel(); + } + SignalLogger.setPath("C:\\Users\\teams\\Desktop\\2025HootLogs"); + SignalLogger.start(); + } + + /** This function is called periodically during operator control. */ + @Override + public void teleopPeriodic() { + } + + @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() { + SimulatedArena.getInstance(); + } + + /** This function is called periodically whilst in simulation. */ + @Override + public void simulationPeriodic() { + SimulatedArena.getInstance().simulationPeriodic(); + } +} \ No newline at end of file diff --git a/2024-2025/main-bot/src/main/java/frc/robot/RobotContainer.java b/2024-2025/main-bot/src/main/java/frc/robot/RobotContainer.java new file mode 100644 index 0000000..24858fa --- /dev/null +++ b/2024-2025/main-bot/src/main/java/frc/robot/RobotContainer.java @@ -0,0 +1,366 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +/* + * This Is The Input List. Whenever Adding A New Input, Make Sure To Add It To The List Below + * + * Driver Controller: + * A - Brake + * B - Point + * Dpad Center - climber + * Back + Y - SysId Dynamic Forward + * Back + X - SysId Dynamic Reverse + * Start + Y - SysId Quasistatic Forward + * Start + X - SysId Quasistatic Reverse + * Left Joystick - Move (Field Orientated) + * Right Joystick - Turn + * LB - Reset Field Centric Seed + * RT - Align with Apriltag + * + * Auxiliary Controller: + * A - Level 1 Elevator + Coral Arm + * B - Level 2 Elevator + Coral Arm + * Y - Level 3 Elevator + Coral Arm + * X - Level 4 Elevator + Coral Arm + * Left Joystick up - Move Elevator up + * Left Joystick down - Move Elevator down + * LB - Coral Arm Up + * RB - Coral Arm Down + * DPad Center - Coral Arm Stop + * LT - Algae intake + * RT - Algae outtake + * + */ + +package frc.robot; + +import static edu.wpi.first.units.Units.*; + +import com.ctre.phoenix6.swerve.SwerveModule.DriveRequestType; +import com.pathplanner.lib.auto.AutoBuilder; +import com.pathplanner.lib.auto.NamedCommands; +import com.pathplanner.lib.commands.PathPlannerAuto; +import com.ctre.phoenix6.swerve.SwerveRequest; +import java.lang.Math; +import frc.robot.Constants.OperatorConstants; +import frc.robot.generated.TunerConstants; +import frc.robot.subsystems.ElevatorSubsystem; +import frc.robot.subsystems.LimeLightSubsystem; +import frc.robot.subsystems.MapleSimSubsystem; +import frc.robot.subsystems.CoralArmSubsystem.CoralArmLevels; +import frc.robot.subsystems.ElevatorSubsystem.ElevatorPresets; +import frc.robot.subsystems.AlgaeArmSubsystem; +import frc.robot.subsystems.ClimberSubsystem; +import frc.robot.subsystems.CommandSwerveDrivetrain; +import frc.robot.subsystems.CoralArmSubsystem; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.Commands; +import edu.wpi.first.wpilibj2.command.InstantCommand; +import edu.wpi.first.wpilibj2.command.button.CommandXboxController; +import edu.wpi.first.wpilibj2.command.button.Trigger; +import edu.wpi.first.math.geometry.Rotation2d; +import edu.wpi.first.wpilibj.smartdashboard.SendableChooser; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; +import edu.wpi.first.wpilibj2.command.RunCommand; +import edu.wpi.first.wpilibj2.command.sysid.SysIdRoutine.Direction; +import edu.wpi.first.wpilibj.DigitalInput; +import frc.robot.subsystems.ElevatorSubsystem.ElevatorPresets; + +/** + * little secret comment OwO This class is where the bulk of the robot should be + * declared. Since Command-based is a "declarative" paradigm, very little robot + * logic should actually be handled in the {@link Robot} periodic methods (other + * than the scheduler calls). Instead, the structure of the robot (including + * subsystems, commands, and trigger mappings) should be declared here. + */ +public class RobotContainer { + // The robot's subsystems and commands are defined here...ElevatorConstants + private final ElevatorSubsystem m_ElevatorSubsystem = new ElevatorSubsystem(); + private final AlgaeArmSubsystem m_AlgaeArmSubsystem = new AlgaeArmSubsystem(); + private final CoralArmSubsystem m_CoralArmSubsystem = new CoralArmSubsystem(); + private final ClimberSubsystem m_ClimberSubsystem = new ClimberSubsystem(); + + // Controllers + private final CommandXboxController m_driverController = new CommandXboxController( + OperatorConstants.kDriverControllerPort); + private final CommandXboxController m_auxillaryController = new CommandXboxController( + Constants.OperatorConstants.kAuxiliaryControllerPort); + + private final SendableChooser autoChooser; + + DigitalInput climberLimitSwitch = new DigitalInput(Constants.ClimberConstants.kClimberLimitSwitchID); + /* Swerve drive platform setup */ // From Swerve Project Generator + + // kSpeedAt12Volts Desired Top speed← + private double MaxSpeed = TunerConstants.kSpeedAt12Volts.in(MetersPerSecond); + // 3/4 of a rotation per second max angular velocity + private double MaxAngularRate = RotationsPerSecond.of(0.75).in(RadiansPerSecond); + + /* Setting up bindings for necessary control of the swerve drive platform */ + private final SwerveRequest.FieldCentric drive = new SwerveRequest.FieldCentric().withDeadband(MaxSpeed * 0.1) + .withRotationalDeadband(MaxAngularRate * 0.1) // Add a 10% deadband + .withDriveRequestType(DriveRequestType.OpenLoopVoltage); // Use open-loop control for drive + // motors + private final SwerveRequest.SwerveDriveBrake brake = new SwerveRequest.SwerveDriveBrake(); + private final SwerveRequest.PointWheelsAt point = new SwerveRequest.PointWheelsAt(); + + private final Telemetry logger = new Telemetry(MaxSpeed); + + public final CommandSwerveDrivetrain m_DrivetrainSubsystem = TunerConstants.createDrivetrain(); + // The following subsystems must be created after the drivetrain + public final LimeLightSubsystem m_LimeLightSubsystem = new LimeLightSubsystem(m_DrivetrainSubsystem); + public final MapleSimSubsystem m_MapleSimSubsystem = new MapleSimSubsystem(m_DrivetrainSubsystem); + + // End of Swerve Drive Platform setup + + /** + * The container for the robot. Contains subsystems, OI devices, and commands. + */ + public RobotContainer() { + + // Build an auto chooser. This will use Commands.none() as the default option. + autoChooser = AutoBuilder.buildAutoChooser(); + + SmartDashboard.putData("Auto Chooser", autoChooser); + + // Register named commands for use in autonomous routines + // NamedCommands.registerCommand("Example Command", + // m_exampleSubsystem.exampleMethodCommand()); + // NamedCommands.registerCommand("MoveElevatorToPresets", + // m_elevatorSubsystem.commandMoveToPreset(null)); + + // Configure the trigger bindings + configureBindings(Math.random()); + } + + /** + * Use this method to define your trigger->command mappings. Triggers can be + * created via the {@link Trigger#Trigger(java.util.function.BooleanSupplier)} + * constructor with an arbitrary predicate, or via the named factories in + * {@link edu.wpi.first.wpilibj2.command.button.CommandGenericHID}'s subclasses + * for {@link CommandXboxController + * Xbox}/{@link edu.wpi.first.wpilibj2.command.button.CommandPS4Controller PS4} + * controllers or {@link edu.wpi.first.wpilibj2.command.button.CommandJoystick + * Flight joysticks}. + * + * @param random + */ + private void configureBindings(double random) { + + // ============================ Elevator Subsystem ============================ + // // + + // Sets the default command for the elevator (the command that always runs) + // Checks if the left joystick is being moved, if it is, it will run the + // commandVoltage method with the left joystick's Y value + // m_ElevatorSubsystem.setDefaultCommand(((Math.abs(m_auxillaryController.getLeftY()) + // > 0.1) && (testMethod())) + // ? m_ElevatorSubsystem.commandVoltage(m_auxillaryController.getLeftY()) + // : m_ElevatorSubsystem.commandVoltage(0)); + + new Trigger(() -> m_auxillaryController.getLeftY() > 0.1).whileTrue(new InstantCommand(() -> { + SmartDashboard.putBoolean("Going Up Triggered", true); + SmartDashboard.putNumber("Y-value", m_auxillaryController.getLeftY()); + m_ElevatorSubsystem.setMotorElevatorSpeed(true); + }, m_ElevatorSubsystem)).onFalse( + new InstantCommand(() -> SmartDashboard.putBoolean("Going Up Triggered", false))); + + new Trigger(() -> m_auxillaryController.getLeftY() < -0.1).whileTrue(new InstantCommand(() -> { + SmartDashboard.putBoolean("Going Down triggered", true); + SmartDashboard.putNumber("Y-value", m_auxillaryController.getLeftY()); + m_ElevatorSubsystem.setMotorElevatorSpeed(false); + })).onFalse(new InstantCommand(() -> SmartDashboard.putBoolean("Going Down triggered", false))); + + // The commands below make the elevator go to certain levels + m_auxillaryController.a() + .onTrue(new InstantCommand( + () -> m_ElevatorSubsystem.moveElevatorToPreset(ElevatorPresets.Level1), + m_ElevatorSubsystem)); + m_auxillaryController.b() + .onTrue(new InstantCommand( + () -> m_ElevatorSubsystem.moveElevatorToPreset(ElevatorPresets.Level2), + m_ElevatorSubsystem)); + m_auxillaryController.y() + .onTrue(new InstantCommand( + () -> m_ElevatorSubsystem.moveElevatorToPreset(ElevatorPresets.Level3), + m_ElevatorSubsystem)); + m_auxillaryController.x() + .onTrue(new InstantCommand( + () -> m_ElevatorSubsystem.moveElevatorToPreset(ElevatorPresets.Level4), + m_ElevatorSubsystem)); + + // ====================== Algae Arm Subsystem ====================== // + + m_auxillaryController.leftTrigger() + // makes algae bar intake if LT pressed + .whileTrue(m_AlgaeArmSubsystem.commandAlgaeIntake(m_AlgaeArmSubsystem)) + // Interrupts the command, causing motors to SLOWLY SPIN INWARDS (this way they + // can maintain control of the algae) + .onFalse(m_AlgaeArmSubsystem.commandInterrupt()); + m_auxillaryController.rightTrigger() + // makes algae bar outtake if RT pressed + .whileTrue(m_AlgaeArmSubsystem.commandAlgaeOuttake(m_AlgaeArmSubsystem)) + // interrupts the command, causing motors to STOP + .onFalse(m_AlgaeArmSubsystem.commandInterrupt()); + + // ====================== Climber Subsystem ====================== // + Trigger climberTrigger = new Trigger(() -> climberLimitSwitch.get()); + climberTrigger.onTrue(m_ClimberSubsystem.runOnce(() -> m_ClimberSubsystem.climberSwitchTriggered())); + m_auxillaryController.povCenter() + .onTrue(m_ClimberSubsystem.runOnce(() -> m_ClimberSubsystem.engageClimber())); + // ====================== Elevator Preset Compositions ====================== // + // Level 1 Preset + // m_auxillaryController.a() + // .onTrue(Commands.sequence( + // m_ElevatorSubsystem + // .commandMoveToPreset(ElevatorPresets.Level1) + // .until(m_ElevatorSubsystem.isElevatorAtDesiredState( + // ElevatorPresets.Level1)), + // m_CoralArmSubsystem + // .CommandsetCoralArmVoltage(0.1, CoralArmLevels.Up) + // .until(m_CoralArmSubsystem.isCoralArmAtDesiredState( + // CoralArmLevels.Up)), + // Commands.waitSeconds(4.2), // Allow the driver time to move up to the + // // reef + // m_CoralArmSubsystem.CommandsetCoralArmVoltage(-0.1, CoralArmLevels.Down) + // .until(m_CoralArmSubsystem.isCoralArmAtDesiredState( + // CoralArmLevels.Down)), + // m_ElevatorSubsystem.commandMoveToPreset(ElevatorPresets.Level1) + // .until(m_ElevatorSubsystem.isElevatorAtDesiredState( + // ElevatorPresets.Level4)))); + // // Level 2 Preset + // m_auxillaryController.b() + // .onTrue(Commands.sequence( + // m_elevatorSubsystem.commandMoveToPreset(ElevatorPresets.Level2) + // .until(m_elevatorSubsystem.isElevatorAtDesiredState(ElevatorPresets.Level2)), + // m_CoralArmSubsystem.CommandsetCoralArmVoltage(0.1, CoralArmLevels.Up) + // .until(m_CoralArmSubsystem.isCoralArmAtDesiredState(CoralArmLevels.Up)), + // Commands.waitSeconds(.5), // Allow the driver time to move up to the reef + // m_CoralArmSubsystem.CommandsetCoralArmVoltage(-0.1, CoralArmLevels.Down) + // .until(m_CoralArmSubsystem.isCoralArmAtDesiredState(CoralArmLevels.Down)), + // m_elevatorSubsystem.commandMoveToPreset(ElevatorPresets.Lowest) + // .until(m_elevatorSubsystem.isElevatorAtDesiredState(ElevatorPresets.Highest)))); + // // Level 3 preset + // m_auxillaryController.y() + // .onTrue(Commands.sequence( + // m_elevatorSubsystem.commandMoveToPreset(ElevatorPresets.Level3) + // .until(m_elevatorSubsystem.isElevatorAtDesiredState(ElevatorPresets.Level3)), + // m_CoralArmSubsystem.CommandsetCoralArmVoltage(0.1, CoralArmLevels.Up) + // .until(m_CoralArmSubsystem.isCoralArmAtDesiredState(CoralArmLevels.Up)), + // Commands.waitSeconds(.5), // Allow the driver time to move up to the reef + // m_CoralArmSubsystem.CommandsetCoralArmVoltage(-0.1, CoralArmLevels.Down) + // .until(m_CoralArmSubsystem.isCoralArmAtDesiredState(CoralArmLevels.Down)), + // m_elevatorSubsystem.commandMoveToPreset(ElevatorPresets.Lowest) + // .until(m_elevatorSubsystem.isElevatorAtDesiredState(ElevatorPresets.Highest)))); + // // Level 4 preset + // m_auxillaryController.x() + // .onTrue(Commands.sequence( + // m_elevatorSubsystem.commandMoveToPreset(ElevatorPresets.Level4) + // .until(m_elevatorSubsystem.isElevatorAtDesiredState(ElevatorPresets.Level4)), + // m_CoralArmSubsystem.CommandsetCoralArmVoltage(0.1, CoralArmLevels.Up) + // .until(m_CoralArmSubsystem.isCoralArmAtDesiredState(CoralArmLevels.Up)), + // Commands.waitSeconds(.5), // Allow the driver time to move up to the reef + // m_CoralArmSubsystem.CommandsetCoralArmVoltage(-0.1, CoralArmLevels.Down) + // .until(m_CoralArmSubsystem.isCoralArmAtDesiredState(CoralArmLevels.Down)), + // m_elevatorSubsystem.commandMoveToPreset(ElevatorPresets.Lowest) + // .until(m_elevatorSubsystem.isElevatorAtDesiredState(ElevatorPresets.Highest)))); + + // ====================== Coral Arm Subsystem ====================== // + // makes coral arm go up + m_auxillaryController.leftBumper() + .whileTrue(m_CoralArmSubsystem.CommandsetCoralArmVoltage(0.2, CoralArmLevels.Up)); + // makes coral arm go down + m_auxillaryController.rightBumper() + .whileTrue(m_CoralArmSubsystem.CommandsetCoralArmVoltage(-0.2, CoralArmLevels.Down)); + // Emergency Stop for Coral Arm (in case it goes past the top or bottom) Note: I + // don't know if the onTrue method will only run once, so test it before you use + // it + m_auxillaryController.povCenter().onTrue(m_CoralArmSubsystem.emergencyStop()); + // stops coral arm + + // ====================== Drive Subsystem ====================== // + // Code below is from swerve drive project generator + + // Note that X is defined as forward according to WPILib convention, + // and Y is defined as to the left according to WPILib convention. + m_DrivetrainSubsystem.setDefaultCommand( + // Drivetrain will execute this command periodically + m_DrivetrainSubsystem.applyRequest(() -> drive + // Drive forward with negative Y (forward) + .withVelocityX(-m_driverController.getLeftY() * MaxSpeed) + // Drive left with negative X (left) + .withVelocityY(-m_driverController.getLeftX() * MaxSpeed) + // Drive counterclockwise with negative X (left) + .withRotationalRate(-m_driverController.getRightX() * MaxAngularRate))); + m_driverController.a().whileTrue(m_DrivetrainSubsystem.applyRequest(() -> brake)); + m_driverController.b().whileTrue(m_DrivetrainSubsystem.applyRequest(() -> point.withModuleDirection( + new Rotation2d(-m_driverController.getLeftY(), -m_driverController.getLeftX())))); + + // limelight override + m_driverController.rightTrigger().whileTrue(m_DrivetrainSubsystem.applyRequest(() -> drive + // Drive forward with negative Y (forward) + .withVelocityX(m_LimeLightSubsystem.limelight_range_proportional()) + // Drive left with negative X (left) + .withVelocityY(-m_driverController.getLeftX() * MaxSpeed) + // Drive counterclockwise with negative X (left) + .withRotationalRate(m_LimeLightSubsystem.limelight_aim_proportional()))); + + // Run SysId routines when holding back/start and X/Y. + // Note that each routine should be run exactly once in a single log. + m_driverController.back().and(m_driverController.y()) + .whileTrue(m_DrivetrainSubsystem.sysIdDynamic(Direction.kForward)); + m_driverController.back().and(m_driverController.x()) + .whileTrue(m_DrivetrainSubsystem.sysIdDynamic(Direction.kReverse)); + m_driverController.start().and(m_driverController.y()) + .whileTrue(m_DrivetrainSubsystem.sysIdQuasistatic(Direction.kForward)); + m_driverController.start().and(m_driverController.x()) + .whileTrue(m_DrivetrainSubsystem.sysIdQuasistatic(Direction.kReverse)); + + // reset the field-centric heading on left bumper press + m_driverController.leftBumper() + .onTrue(m_DrivetrainSubsystem.runOnce(() -> m_DrivetrainSubsystem.seedFieldCentric())); + + m_DrivetrainSubsystem.registerTelemetry(logger::telemeterize); + + } + + /** + * 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.getSelected(); + } +} +// another why not comment :) +// I do love some good comments :D + +// Saw this code in another teams robot and took it, may be interesting to +// implement +// Endgame alert triggers + +// new Trigger( +// () -> +// DriverStation.isTeleopEnabled() +// && DriverStation.getMatchTime() > 0 +// && DriverStation.getMatchTime() <= Math.round(endgameAlert1.get())) +// .onTrue( +// controllerRumbleCommand() +// .withTimeout(0.5) +// .beforeStarting(() -> Leds.getInstance().endgameAlert = true) +// .finallyDo(() -> Leds.getInstance().endgameAlert = false)); +// new Trigger( +// () -> +// DriverStation.isTeleopEnabled() +// && DriverStation.getMatchTime() > 0 +// && DriverStation.getMatchTime() <= Math.round(endgameAlert2.get())) +// .onTrue( +// controllerRumbleCommand() +// .withTimeout(0.2) +// .andThen(Commands.waitSeconds(0.1)) +// .repeatedly() +// .withTimeout(0.9) // Rumble three times +// .beforeStarting(() -> Leds.getInstance().endgameAlert = true) +// .finallyDo(() -> Leds.getInstance().endgameAlert = false)); \ No newline at end of file diff --git a/2024-2025/main-bot/src/main/java/frc/robot/Telemetry.java b/2024-2025/main-bot/src/main/java/frc/robot/Telemetry.java new file mode 100644 index 0000000..d00e7b5 --- /dev/null +++ b/2024-2025/main-bot/src/main/java/frc/robot/Telemetry.java @@ -0,0 +1,125 @@ +package frc.robot; + +import com.ctre.phoenix6.SignalLogger; +import com.ctre.phoenix6.swerve.SwerveDrivetrain.SwerveDriveState; + +import edu.wpi.first.math.geometry.Pose2d; +import edu.wpi.first.math.kinematics.ChassisSpeeds; +import edu.wpi.first.math.kinematics.SwerveModulePosition; +import edu.wpi.first.math.kinematics.SwerveModuleState; +import edu.wpi.first.networktables.DoubleArrayPublisher; +import edu.wpi.first.networktables.DoublePublisher; +import edu.wpi.first.networktables.NetworkTable; +import edu.wpi.first.networktables.NetworkTableInstance; +import edu.wpi.first.networktables.StringPublisher; +import edu.wpi.first.networktables.StructArrayPublisher; +import edu.wpi.first.networktables.StructPublisher; +import edu.wpi.first.wpilibj.smartdashboard.Mechanism2d; +import edu.wpi.first.wpilibj.smartdashboard.MechanismLigament2d; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; +import edu.wpi.first.wpilibj.util.Color; +import edu.wpi.first.wpilibj.util.Color8Bit; + +public class Telemetry { + private final double MaxSpeed; + + /** + * Construct a telemetry object, with the specified max speed of the robot + * + * @param maxSpeed Maximum speed in meters per second + */ + public Telemetry(double maxSpeed) { + MaxSpeed = maxSpeed; + SignalLogger.start(); + } + + /* What to publish over networktables for telemetry */ + private final NetworkTableInstance inst = NetworkTableInstance.getDefault(); + + /* Robot swerve drive state */ + private final NetworkTable driveStateTable = inst.getTable("DriveState"); + private final StructPublisher drivePose = driveStateTable.getStructTopic("Pose", Pose2d.struct).publish(); + private final StructPublisher driveSpeeds = driveStateTable.getStructTopic("Speeds", ChassisSpeeds.struct).publish(); + private final StructArrayPublisher driveModuleStates = driveStateTable.getStructArrayTopic("ModuleStates", SwerveModuleState.struct).publish(); + private final StructArrayPublisher driveModuleTargets = driveStateTable.getStructArrayTopic("ModuleTargets", SwerveModuleState.struct).publish(); + private final StructArrayPublisher driveModulePositions = driveStateTable.getStructArrayTopic("ModulePositions", SwerveModulePosition.struct).publish(); + private final DoublePublisher driveTimestamp = driveStateTable.getDoubleTopic("Timestamp").publish(); + private final DoublePublisher driveOdometryFrequency = driveStateTable.getDoubleTopic("OdometryFrequency").publish(); + + /* Robot pose for field positioning */ + private final NetworkTable table = inst.getTable("Pose"); + private final DoubleArrayPublisher fieldPub = table.getDoubleArrayTopic("robotPose").publish(); + private final StringPublisher fieldTypePub = table.getStringTopic(".type").publish(); + + /* Mechanisms to represent the swerve module states */ + private final Mechanism2d[] m_moduleMechanisms = new Mechanism2d[] { + new Mechanism2d(1, 1), + new Mechanism2d(1, 1), + new Mechanism2d(1, 1), + new Mechanism2d(1, 1), + }; + /* A direction and length changing ligament for speed representation */ + private final MechanismLigament2d[] m_moduleSpeeds = new MechanismLigament2d[] { + m_moduleMechanisms[0].getRoot("RootSpeed", 0.5, 0.5).append(new MechanismLigament2d("Speed", 0.5, 0)), + m_moduleMechanisms[1].getRoot("RootSpeed", 0.5, 0.5).append(new MechanismLigament2d("Speed", 0.5, 0)), + m_moduleMechanisms[2].getRoot("RootSpeed", 0.5, 0.5).append(new MechanismLigament2d("Speed", 0.5, 0)), + m_moduleMechanisms[3].getRoot("RootSpeed", 0.5, 0.5).append(new MechanismLigament2d("Speed", 0.5, 0)), + }; + /* A direction changing and length constant ligament for module direction */ + private final MechanismLigament2d[] m_moduleDirections = new MechanismLigament2d[] { + m_moduleMechanisms[0].getRoot("RootDirection", 0.5, 0.5) + .append(new MechanismLigament2d("Direction", 0.1, 0, 0, new Color8Bit(Color.kWhite))), + m_moduleMechanisms[1].getRoot("RootDirection", 0.5, 0.5) + .append(new MechanismLigament2d("Direction", 0.1, 0, 0, new Color8Bit(Color.kWhite))), + m_moduleMechanisms[2].getRoot("RootDirection", 0.5, 0.5) + .append(new MechanismLigament2d("Direction", 0.1, 0, 0, new Color8Bit(Color.kWhite))), + m_moduleMechanisms[3].getRoot("RootDirection", 0.5, 0.5) + .append(new MechanismLigament2d("Direction", 0.1, 0, 0, new Color8Bit(Color.kWhite))), + }; + + private final double[] m_poseArray = new double[3]; + private final double[] m_moduleStatesArray = new double[8]; + private final double[] m_moduleTargetsArray = new double[8]; + + /** Accept the swerve drive state and telemeterize it to SmartDashboard and SignalLogger. */ + //Secret OwO comment #1 + public void telemeterize(SwerveDriveState state) { + /* Telemeterize the swerve drive state */ + drivePose.set(state.Pose); + driveSpeeds.set(state.Speeds); + driveModuleStates.set(state.ModuleStates); + driveModuleTargets.set(state.ModuleTargets); + driveModulePositions.set(state.ModulePositions); + driveTimestamp.set(state.Timestamp); + driveOdometryFrequency.set(1.0 / state.OdometryPeriod); + + /* Also write to log file */ + m_poseArray[0] = state.Pose.getX(); + m_poseArray[1] = state.Pose.getY(); + m_poseArray[2] = state.Pose.getRotation().getDegrees(); + for (int i = 0; i < 4; ++i) { + m_moduleStatesArray[i*2 + 0] = state.ModuleStates[i].angle.getRadians(); + m_moduleStatesArray[i*2 + 1] = state.ModuleStates[i].speedMetersPerSecond; + m_moduleTargetsArray[i*2 + 0] = state.ModuleTargets[i].angle.getRadians(); + m_moduleTargetsArray[i*2 + 1] = state.ModuleTargets[i].speedMetersPerSecond; + } + + SignalLogger.writeDoubleArray("DriveState/Pose", m_poseArray); + SignalLogger.writeDoubleArray("DriveState/ModuleStates", m_moduleStatesArray); + SignalLogger.writeDoubleArray("DriveState/ModuleTargets", m_moduleTargetsArray); + SignalLogger.writeDouble("DriveState/OdometryPeriod", state.OdometryPeriod, "seconds"); + + /* Telemeterize the pose to a Field2d */ + fieldTypePub.set("Field2d"); + fieldPub.set(m_poseArray); + + /* Telemeterize the module states to a Mechanism2d */ + for (int i = 0; i < 4; ++i) { + m_moduleSpeeds[i].setAngle(state.ModuleStates[i].angle); + m_moduleDirections[i].setAngle(state.ModuleStates[i].angle); + m_moduleSpeeds[i].setLength(state.ModuleStates[i].speedMetersPerSecond / (2 * MaxSpeed)); + + SmartDashboard.putData("Module " + i, m_moduleMechanisms[i]); + } + } +} diff --git a/2024-2025/main-bot/src/main/java/frc/robot/Utility.java b/2024-2025/main-bot/src/main/java/frc/robot/Utility.java new file mode 100644 index 0000000..99169cf --- /dev/null +++ b/2024-2025/main-bot/src/main/java/frc/robot/Utility.java @@ -0,0 +1,135 @@ +package frc.robot; + +import edu.wpi.first.wpilibj.DriverStation; + +/** + * The {@code Utility} class is used to store general methods that are used + * throughout the code. + *

+ * Current methods include: + *

    + *
  • {@link Utility#printLn}
  • + *
  • {@link Utility#clamp}
  • + *
  • {@link Utility#snapToEdge}
  • + *
+ * Additional methods may be added in the future if and when they are needed. + *

+ */ +public final class Utility { + + // Constructor // + // This is set to private as this is a utility class and + // should not be instantiated + // private Utility() { + // throw new UnsupportedOperationException( + // "This is a utility class and cannot be instantiated"); + // } + + /** + * The {@code printCounter} variable is used to count how many times the + * {@code System.out.println} method has been called. + * This is used in the {@link Utility#printLn} method. + */ + private static int printCounter = 0; + + /** + * The {@code printLn} method is used to print a message to the + * console every 50 times it is called. + * This is to slow down the messages as it overwhlems the roboRIO + * and causes the console to lag. + * + * @param messageString String to print to the console + * + * @see Utility#printCounter + */ + public static void printLn(final String messageString) {//i dont have any idea what this does but it's here so yay + if (printCounter == 50) { + System.out.println(messageString); + printCounter = 0; + } else { + printCounter++; + } + } + + /** + * The {@code log} method is similar to the printLn method. + * Instead of just printing a message, it will send it through DriverStation. + * THe values of the log type goes as follows: + * - 0 -> Info + * - 1 -> Warn + * - 3 -> Error + * @param messageString + * @param logType + */ + public static void log(final String messageString, final int logType) { + if (!(printCounter == 50)) { + printCounter++; + } + + if (logType == 1) { + System.out.println(messageString); + } else if (logType == 2) { + DriverStation.reportWarning(messageString, null); + } else if (logType == 3) { + DriverStation.reportError(messageString, null); + } + } + + + + + + + + + + + + + + + + + + + // BELOW ARE THE METHODS THAT ARE NOT USED IN THE CODE (IMPORTS FROM LAST YEAR) + + // /** + // * The {@code clamp} method is used to clamp a value between a minimum and + // * maximum value. + // *

+ // * If the value is less than the minimum, the minimum is returned. + // * If the value is greater than the maximum, the maximum is returned. + // * If the value is between the minimum and maximum, the value is returned. + // *

+ // * + // * @param value Value to clamp + // * @param min Minimum value + // * @param max Maximum value + // * + // * @return The clamped value + // */ + // public static double clamp(final double value, final double min, + // final double max) { + // return value < min ? min : value > max ? max : value; + // } + + // /** + // * Snap a value to the minimum or maximum value only if it is within a + // * threshold. + // * Although similar to the {@link Utility#clamp} method, + // * this method is used to snap a value to the minimum or maximum value + // * if it iswithin a threshold + // * + // * @param value Value to snap + // * @param min Minimum value + // * @param max Maximum value + // * @param threshold Threshold to snap to + // * + // * @return The snapped value + // */ + // public static double snapToEdge(final double value, final double min, + // final double max, final double threshold) { + // return value < -threshold ? min : value > threshold ? max : value; + // } +} diff --git a/2024-2025/main-bot/src/main/java/frc/robot/generated/TunerConstants.java b/2024-2025/main-bot/src/main/java/frc/robot/generated/TunerConstants.java new file mode 100644 index 0000000..bcf08ff --- /dev/null +++ b/2024-2025/main-bot/src/main/java/frc/robot/generated/TunerConstants.java @@ -0,0 +1,225 @@ +package frc.robot.generated; + +import static edu.wpi.first.units.Units.*; + +import com.ctre.phoenix6.CANBus; +import com.ctre.phoenix6.configs.*; +import com.ctre.phoenix6.hardware.*; +import com.ctre.phoenix6.signals.*; +import com.ctre.phoenix6.swerve.*; +import com.ctre.phoenix6.swerve.SwerveModuleConstants.*; + +import edu.wpi.first.math.Matrix; +import edu.wpi.first.math.numbers.N1; +import edu.wpi.first.math.numbers.N3; +import edu.wpi.first.units.measure.*; +import frc.robot.Constants; +import frc.robot.subsystems.CommandSwerveDrivetrain; + +// Generated by the Tuner X Swerve Project Generator +// https://v6.docs.ctr-electronics.com/en/stable/docs/tuner/tuner-swerve/index.html +public class TunerConstants { + // Both sets of gains need to be tuned to your individual robot. + + // The steer motor uses any SwerveModule.SteerRequestType control request with + // the + // output type specified by SwerveModuleConstants.SteerMotorClosedLoopOutput + private static final Slot0Configs steerGains = new Slot0Configs().withKP(100).withKI(0).withKD(0.5).withKS(0.1) + .withKV(1.66).withKA(0).withStaticFeedforwardSign(StaticFeedforwardSignValue.UseClosedLoopSign); + // When using closed-loop control, the drive motor uses the control + // output type specified by SwerveModuleConstants.DriveMotorClosedLoopOutput + private static final Slot0Configs driveGains = new Slot0Configs().withKP(0.1).withKI(0).withKD(0).withKS(0) + .withKV(0.124); + + // The closed-loop output type to use for the steer motors; + // This affects the PID/FF gains for the steer motors + private static final ClosedLoopOutputType kSteerClosedLoopOutput = ClosedLoopOutputType.Voltage; + // The closed-loop output type to use for the drive motors; + // This affects the PID/FF gains for the drive motors + private static final ClosedLoopOutputType kDriveClosedLoopOutput = ClosedLoopOutputType.Voltage; + + // The type of motor used for the drive motor + private static final DriveMotorArrangement kDriveMotorType = DriveMotorArrangement.TalonFX_Integrated; + // The type of motor used for the drive motor + private static final SteerMotorArrangement kSteerMotorType = SteerMotorArrangement.TalonFX_Integrated; + + // The remote sensor feedback type to use for the steer motors; + // When not Pro-licensed, Fused*/Sync* automatically fall back to Remote* + private static final SteerFeedbackType kSteerFeedbackType = SteerFeedbackType.FusedCANcoder; + + // The stator current at which the wheels start to slip; + // This needs to be tuned to your individual robot + private static final Current kSlipCurrent = Amps.of(120.0); + + // Initial configs for the drive and steer motors and the azimuth encoder; these + // cannot be null. + // Some configs will be overwritten; check the `with*InitialConfigs()` API + // documentation. + private static final TalonFXConfiguration driveInitialConfigs = new TalonFXConfiguration(); + private static final TalonFXConfiguration steerInitialConfigs = new TalonFXConfiguration() + .withCurrentLimits(new CurrentLimitsConfigs() + // Swerve azimuth does not require much torque output, so we can set a + // relatively low + // stator current limit to help avoid brownouts without impacting performance. + .withStatorCurrentLimit(Amps.of(60)).withStatorCurrentLimitEnable(true)); + private static final CANcoderConfiguration encoderInitialConfigs = new CANcoderConfiguration(); + // Configs for the Pigeon 2; leave this null to skip applying Pigeon 2 configs + private static final Pigeon2Configuration pigeonConfigs = null; + + // CAN bus that the devices are located on; + // All swerve devices must share the same CAN bus + public static final CANBus kCANBus = new CANBus("", "./logs/example.hoot"); + + // Theoretical free speed (m/s) at 12 V applied output; + // This needs to be tuned to your individual robot + public static final LinearVelocity kSpeedAt12Volts = MetersPerSecond.of(6.95); + + // Every 1 rotation of the azimuth results in kCoupleRatio drive motor turns; + // This may need to be tuned to your individual robot + private static final double kCoupleRatio = 3.5; + + private static final double kDriveGearRatio = 4.59375; + private static final double kSteerGearRatio = 13.371428571428572; + private static final Distance kWheelRadius = Inches.of(2); + + private static final boolean kInvertLeftSide = false; + private static final boolean kInvertRightSide = true; + + private static final int kPigeonId = 20; + + // These are only used for simulation + private static final MomentOfInertia kSteerInertia = KilogramSquareMeters.of(0.01); + private static final MomentOfInertia kDriveInertia = KilogramSquareMeters.of(0.01); + // Simulated voltage necessary to overcome friction + private static final Voltage kSteerFrictionVoltage = Volts.of(0.2); + private static final Voltage kDriveFrictionVoltage = Volts.of(0.2); + + public static final SwerveDrivetrainConstants DrivetrainConstants = new SwerveDrivetrainConstants() + .withCANBusName(kCANBus.getName()).withPigeon2Id(kPigeonId).withPigeon2Configs(pigeonConfigs); + + private static final SwerveModuleConstantsFactory ConstantCreator = new SwerveModuleConstantsFactory() + .withDriveMotorGearRatio(kDriveGearRatio).withSteerMotorGearRatio(kSteerGearRatio) + .withCouplingGearRatio(kCoupleRatio).withWheelRadius(kWheelRadius) + .withSteerMotorGains(steerGains).withDriveMotorGains(driveGains) + .withSteerMotorClosedLoopOutput(kSteerClosedLoopOutput) + .withDriveMotorClosedLoopOutput(kDriveClosedLoopOutput).withSlipCurrent(kSlipCurrent) + .withSpeedAt12Volts(kSpeedAt12Volts).withDriveMotorType(kDriveMotorType) + .withSteerMotorType(kSteerMotorType).withFeedbackSource(kSteerFeedbackType) + .withDriveMotorInitialConfigs(driveInitialConfigs) + .withSteerMotorInitialConfigs(steerInitialConfigs) + .withEncoderInitialConfigs(encoderInitialConfigs).withSteerInertia(kSteerInertia) + .withDriveInertia(kDriveInertia).withSteerFrictionVoltage(kSteerFrictionVoltage) + .withDriveFrictionVoltage(kDriveFrictionVoltage); + + public static final SwerveModuleConstants FrontLeft = ConstantCreator + .createModuleConstants(Constants.DriveTrainConstants.kFrontLeftSteerMotorId, + Constants.DriveTrainConstants.kFrontLeftDriveMotorId, + Constants.DriveTrainConstants.kFrontLeftEncoderId, + Constants.DriveTrainConstants.kFrontLeftEncoderOffset, + Constants.DriveTrainConstants.kFrontLeftXPos, + Constants.DriveTrainConstants.kFrontLeftYPos, kInvertLeftSide, + Constants.DriveTrainConstants.kFrontLeftSteerMotorInverted, + Constants.DriveTrainConstants.kFrontLeftEncoderInverted); + public static final SwerveModuleConstants FrontRight = ConstantCreator + .createModuleConstants(Constants.DriveTrainConstants.kFrontRightSteerMotorId, + Constants.DriveTrainConstants.kFrontRightDriveMotorId, + Constants.DriveTrainConstants.kFrontRightEncoderId, + Constants.DriveTrainConstants.kFrontRightEncoderOffset, + Constants.DriveTrainConstants.kFrontRightXPos, + Constants.DriveTrainConstants.kFrontRightYPos, kInvertRightSide, + Constants.DriveTrainConstants.kFrontRightSteerMotorInverted, + Constants.DriveTrainConstants.kFrontRightEncoderInverted); + public static final SwerveModuleConstants BackLeft = ConstantCreator + .createModuleConstants(Constants.DriveTrainConstants.kBackLeftSteerMotorId, + Constants.DriveTrainConstants.kBackLeftDriveMotorId, + Constants.DriveTrainConstants.kBackLeftEncoderId, + Constants.DriveTrainConstants.kBackLeftEncoderOffset, + Constants.DriveTrainConstants.kBackLeftXPos, + Constants.DriveTrainConstants.kBackLeftYPos, kInvertLeftSide, + Constants.DriveTrainConstants.kBackLeftSteerMotorInverted, + Constants.DriveTrainConstants.kBackLeftEncoderInverted); + public static final SwerveModuleConstants BackRight = ConstantCreator + .createModuleConstants(Constants.DriveTrainConstants.kBackRightSteerMotorId, + Constants.DriveTrainConstants.kBackRightDriveMotorId, + Constants.DriveTrainConstants.kBackRightEncoderId, + Constants.DriveTrainConstants.kBackRightEncoderOffset, + Constants.DriveTrainConstants.kBackRightXPos, + Constants.DriveTrainConstants.kBackRightYPos, kInvertRightSide, + Constants.DriveTrainConstants.kBackRightSteerMotorInverted, + Constants.DriveTrainConstants.kBackRightEncoderInverted); + + /** + * Creates a CommandSwerveDrivetrain instance. This should only be called once + * in your robot program,. + */ + public static CommandSwerveDrivetrain createDrivetrain() { + return new CommandSwerveDrivetrain(DrivetrainConstants, FrontLeft, FrontRight, BackLeft, BackRight); + } + + /** + * Swerve Drive class utilizing CTR Electronics' Phoenix 6 API with the selected + * device types. + */ + public static class TunerSwerveDrivetrain extends SwerveDrivetrain { + /** + * Constructs a CTRE SwerveDrivetrain using the specified constants. + *

+ * This constructs the underlying hardware devices, so users should not + * construct the devices themselves. If they need the devices, they can access + * them through getters in the classes. + * + * @param drivetrainConstants Drivetrain-wide constants for the swerve drive + * @param modules Constants for each specific module + */ + public TunerSwerveDrivetrain(SwerveDrivetrainConstants drivetrainConstants, + SwerveModuleConstants... modules) { + super(TalonFX::new, TalonFX::new, CANcoder::new, drivetrainConstants, modules); + } + + /** + * Constructs a CTRE SwerveDrivetrain using the specified constants. + *

+ * This constructs the underlying hardware devices, so users should not + * construct the devices themselves. If they need the devices, they can access + * them through getters in the classes. + * + * @param drivetrainConstants Drivetrain-wide constants for the swerve drive + * @param odometryUpdateFrequency The frequency to run the odometry loop. If + * unspecified or set to 0 Hz, this is 250 Hz on + * CAN FD, and 100 Hz on CAN 2.0. + * @param modules Constants for each specific module + */ + public TunerSwerveDrivetrain(SwerveDrivetrainConstants drivetrainConstants, + double odometryUpdateFrequency, SwerveModuleConstants... modules) { + super(TalonFX::new, TalonFX::new, CANcoder::new, drivetrainConstants, odometryUpdateFrequency, + modules); + } + + /** + * Constructs a CTRE SwerveDrivetrain using the specified constants. + *

+ * This constructs the underlying hardware devices, so users should not + * construct the devices themselves. If they need the devices, they can access + * them through getters in the classes. + * + * @param drivetrainConstants Drivetrain-wide constants for the swerve + * drive + * @param odometryUpdateFrequency The frequency to run the odometry loop. If + * unspecified or set to 0 Hz, this is 250 Hz + * on CAN FD, and 100 Hz on CAN 2.0. + * @param odometryStandardDeviation The standard deviation for odometry + * calculation in the form [x, y, theta]ᵀ, with + * units in meters and radians + * @param visionStandardDeviation The standard deviation for vision + * calculation in the form [x, y, theta]ᵀ, with + * units in meters and radians + * @param modules Constants for each specific module + */ + public TunerSwerveDrivetrain(SwerveDrivetrainConstants drivetrainConstants, + double odometryUpdateFrequency, Matrix odometryStandardDeviation, + Matrix visionStandardDeviation, SwerveModuleConstants... modules) { + super(TalonFX::new, TalonFX::new, CANcoder::new, drivetrainConstants, odometryUpdateFrequency, + odometryStandardDeviation, visionStandardDeviation, modules); + } + } +} diff --git a/2024-2025/main-bot/src/main/java/frc/robot/subsystems/AlgaeArmSubsystem.java b/2024-2025/main-bot/src/main/java/frc/robot/subsystems/AlgaeArmSubsystem.java new file mode 100644 index 0000000..a11ebbb --- /dev/null +++ b/2024-2025/main-bot/src/main/java/frc/robot/subsystems/AlgaeArmSubsystem.java @@ -0,0 +1,74 @@ +package frc.robot.subsystems; + +//import edu.wpi.first.wpilibj.DigitalInput; +//import edu.wpi.first.wpilibj.Joystick; +//import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; + +import com.ctre.phoenix.motorcontrol.ControlMode; +import com.ctre.phoenix.motorcontrol.can.TalonSRX; +import edu.wpi.first.wpilibj2.command.SubsystemBase; +//import edu.wpi.first.wpilibj2.command.button.CommandXboxController; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.Commands; +import frc.robot.Constants.AlgaeArmConstants; + +public class AlgaeArmSubsystem extends SubsystemBase { + + // Motors + private final TalonSRX m_algaeBarMotor; + + // Initialized Stuff + public AlgaeArmSubsystem() { + m_algaeBarMotor = new TalonSRX(AlgaeArmConstants.algaeArmBarMotorID); + } + + public Command commandMakeBarSpin(boolean APressed, boolean BPressed, boolean YPressed) {// makes, well, the bar + // spin + return runOnce(() -> { + if (APressed) { + setAlgaeArmVoltage(0.5);// מציין מיקום man it sure is nice to hide secret messages in hebrew hungarian + // and albanian in that specific order + } else if (BPressed) { + setAlgaeArmVoltage(-0.25);// helyőrző + } else if (YPressed) { + setAlgaeArmVoltage(0.25);// vendmbajtes + } else { + setAlgaeArmVoltage(0); + } + }); + } + + public void setAlgaeArmVoltage(double voltage) {// place to move da algae bar + m_algaeBarMotor.set(ControlMode.PercentOutput, voltage);// moves da algae bar + } + + public Command PrintRand() { + return runOnce(() -> { + System.out.println(Math.random() * 100); + }// a curly brace + );// a parenthesis followed by a semicolon + }// a curly brace + + // who placed these here? They lowkey clash wittewawy -_- + public Command commandAlgaeIntake(AlgaeArmSubsystem algaeArmSubsystem) { + return Commands.startEnd(() -> m_algaeBarMotor.set(ControlMode.PercentOutput, 0.3), // placeholder + () -> m_algaeBarMotor.set(ControlMode.PercentOutput, 0.1), // placeholder + algaeArmSubsystem); + } + + public Command commandAlgaeOuttake(AlgaeArmSubsystem algaeArmSubsystem) { + return Commands.startEnd(() -> m_algaeBarMotor.set(ControlMode.PercentOutput, -0.3), // placeholder + () -> m_algaeBarMotor.set(ControlMode.PercentOutput, 0), // placeholder + algaeArmSubsystem); + } + + public Command commandInterrupt() { + return runOnce(() -> { + ; + // This command has not other purpose than to interrupt the algae arm + // Causing the end conditions of the .startEnd() commands to be met + }); + } + +} +// a curly brace \ No newline at end of file diff --git a/2024-2025/main-bot/src/main/java/frc/robot/subsystems/ClimberSubsystem.java b/2024-2025/main-bot/src/main/java/frc/robot/subsystems/ClimberSubsystem.java new file mode 100644 index 0000000..941fc67 --- /dev/null +++ b/2024-2025/main-bot/src/main/java/frc/robot/subsystems/ClimberSubsystem.java @@ -0,0 +1,31 @@ +package frc.robot.subsystems; + +import com.ctre.phoenix6.hardware.TalonFX; + +import edu.wpi.first.wpilibj.DigitalInput; +import edu.wpi.first.wpilibj2.command.SubsystemBase; +import frc.robot.Logging; +import frc.robot.Constants.ClimberConstants; + +// Must change logging + +public class ClimberSubsystem extends SubsystemBase { + private boolean switchFlipped = false; + private TalonFX leftClimberMotor; + private TalonFX rightClimberMotor; + + public ClimberSubsystem() { + leftClimberMotor = new TalonFX(ClimberConstants.kLeftClimberMotorID); + rightClimberMotor = new TalonFX(ClimberConstants.kRightClimberMotorID); + } + + public void climberSwitchTriggered() { + switchFlipped = true; + } + + public void engageClimber() { + leftClimberMotor.set(0.1); + rightClimberMotor.set(-0.1); + } + +} \ No newline at end of file diff --git a/2024-2025/main-bot/src/main/java/frc/robot/subsystems/CommandSwerveDrivetrain.java b/2024-2025/main-bot/src/main/java/frc/robot/subsystems/CommandSwerveDrivetrain.java new file mode 100644 index 0000000..3566d94 --- /dev/null +++ b/2024-2025/main-bot/src/main/java/frc/robot/subsystems/CommandSwerveDrivetrain.java @@ -0,0 +1,306 @@ +package frc.robot.subsystems; + +import static edu.wpi.first.units.Units.*; + +import java.util.function.Supplier; + +import com.ctre.phoenix6.SignalLogger; +import com.ctre.phoenix6.Utils; +import com.ctre.phoenix6.swerve.SwerveDrivetrainConstants; +import com.ctre.phoenix6.swerve.SwerveModuleConstants; +import com.ctre.phoenix6.swerve.SwerveRequest; +import com.pathplanner.lib.auto.AutoBuilder; +import com.pathplanner.lib.config.PIDConstants; +import com.pathplanner.lib.config.RobotConfig; +import com.pathplanner.lib.controllers.PPHolonomicDriveController; + +import edu.wpi.first.math.Matrix; +import edu.wpi.first.math.geometry.Pose2d; +import edu.wpi.first.math.geometry.Rotation2d; +import edu.wpi.first.math.numbers.N1; +import edu.wpi.first.math.numbers.N3; +import edu.wpi.first.wpilibj.DriverStation; +import edu.wpi.first.wpilibj.DriverStation.Alliance; +import edu.wpi.first.wpilibj.Notifier; +import edu.wpi.first.wpilibj.RobotController; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.Subsystem; +import edu.wpi.first.wpilibj2.command.sysid.SysIdRoutine; + +import frc.robot.generated.TunerConstants.TunerSwerveDrivetrain; + +/** + * Class that extends the Phoenix 6 SwerveDrivetrain class and implements + * Subsystem so it can easily be used in command-based projects. + */ +public class CommandSwerveDrivetrain extends TunerSwerveDrivetrain implements Subsystem { + private static final double kSimLoopPeriod = 0.005; // 5 ms + private Notifier m_simNotifier = null; + private double m_lastSimTime; + + /* Blue alliance sees forward as 0 degrees (toward red alliance wall) */ + private static final Rotation2d kBlueAlliancePerspectiveRotation = Rotation2d.kZero; + /* Red alliance sees forward as 180 degrees (toward blue alliance wall) */ + private static final Rotation2d kRedAlliancePerspectiveRotation = Rotation2d.k180deg; + /* Keep track if we've ever applied the operator perspective before or not */ + private boolean m_hasAppliedOperatorPerspective = false; + + /** Swerve request to apply during robot-centric path following */ + private final SwerveRequest.ApplyRobotSpeeds m_pathApplyRobotSpeeds = new SwerveRequest.ApplyRobotSpeeds(); + + /* Swerve requests to apply during SysId characterization */ + private final SwerveRequest.SysIdSwerveTranslation m_translationCharacterization = new SwerveRequest.SysIdSwerveTranslation(); + private final SwerveRequest.SysIdSwerveSteerGains m_steerCharacterization = new SwerveRequest.SysIdSwerveSteerGains(); + private final SwerveRequest.SysIdSwerveRotation m_rotationCharacterization = new SwerveRequest.SysIdSwerveRotation(); + + /* + * SysId routine for characterizing translation. This is used to find PID gains + * for the drive motors. + */ + private final SysIdRoutine m_sysIdRoutineTranslation = new SysIdRoutine(new SysIdRoutine.Config(null, // Use default + // ramp rate + // (1 V/s) + Volts.of(4), // Reduce dynamic step voltage to 4 V to prevent brownout + null, // Use default timeout (10 s) + // Log state with SignalLogger class + state -> SignalLogger.writeString("SysIdTranslation_State", state.toString())), + new SysIdRoutine.Mechanism(output -> setControl(m_translationCharacterization.withVolts(output)), null, + this)); + + /* + * SysId routine for characterizing steer. This is used to find PID gains for + * the steer motors. + */ + private final SysIdRoutine m_sysIdRoutineSteer = new SysIdRoutine(new SysIdRoutine.Config(null, // Use default ramp + // rate (1 V/s) + Volts.of(7), // Use dynamic voltage of 7 V + null, // Use default timeout (10 s) + // Log state with SignalLogger class + state -> SignalLogger.writeString("SysIdSteer_State", state.toString())), + new SysIdRoutine.Mechanism(volts -> setControl(m_steerCharacterization.withVolts(volts)), null, this)); + + /* + * SysId routine for characterizing rotation. This is used to find PID gains for + * the FieldCentricFacingAngle HeadingController. See the documentation of + * SwerveRequest.SysIdSwerveRotation for info on importing the log to SysId. + */ + private final SysIdRoutine m_sysIdRoutineRotation = new SysIdRoutine(new SysIdRoutine.Config( + /* This is in radians per second², but SysId only supports "volts per second" */ + Volts.of(Math.PI / 6).per(Second), + /* This is in radians per second, but SysId only supports "volts" */ + Volts.of(Math.PI), null, // Use default timeout (10 s) + // Log state with SignalLogger class + state -> SignalLogger.writeString("SysIdRotation_State", state.toString())), + new SysIdRoutine.Mechanism(output -> { + /* output is actually radians per second, but SysId only supports "volts" */ + setControl(m_rotationCharacterization.withRotationalRate(output.in(Volts))); + /* also log the requested output for SysId */ + SignalLogger.writeDouble("Rotational_Rate", output.in(Volts)); + }, null, this)); + + /* The SysId routine to test */ + private SysIdRoutine m_sysIdRoutineToApply = m_sysIdRoutineTranslation; + + /** + * Constructs a CTRE SwerveDrivetrain using the specified constants. + *

+ * This constructs the underlying hardware devices, so users should not + * construct the devices themselves. If they need the devices, they can access + * them through getters in the classes. + * + * @param drivetrainConstants Drivetrain-wide constants for the swerve drive + * @param modules Constants for each specific module + */ + public CommandSwerveDrivetrain(SwerveDrivetrainConstants drivetrainConstants, + SwerveModuleConstants... modules) { + super(drivetrainConstants, modules); + if (Utils.isSimulation()) { + startSimThread(); + } + configureAutoBuilder(); + } + + /** + * Constructs a CTRE SwerveDrivetrain using the specified constants. + *

+ * This constructs the underlying hardware devices, so users should not + * construct the devices themselves. If they need the devices, they can access + * them through getters in the classes. + * + * @param drivetrainConstants Drivetrain-wide constants for the swerve drive + * @param odometryUpdateFrequency The frequency to run the odometry loop. If + * unspecified or set to 0 Hz, this is 250 Hz on + * CAN FD, and 100 Hz on CAN 2.0. + * @param modules Constants for each specific module + */ + public CommandSwerveDrivetrain(SwerveDrivetrainConstants drivetrainConstants, double odometryUpdateFrequency, + SwerveModuleConstants... modules) { + super(drivetrainConstants, odometryUpdateFrequency, modules); + if (Utils.isSimulation()) { + startSimThread(); + } + configureAutoBuilder(); + } + + /** + * Constructs a CTRE SwerveDrivetrain using the specified constants. + *

+ * This constructs the underlying hardware devices, so users should not + * construct the devices themselves. If they need the devices, they can access + * them through getters in the classes. + * + * @param drivetrainConstants Drivetrain-wide constants for the swerve + * drive + * @param odometryUpdateFrequency The frequency to run the odometry loop. If + * unspecified or set to 0 Hz, this is 250 Hz + * on CAN FD, and 100 Hz on CAN 2.0. + * @param odometryStandardDeviation The standard deviation for odometry + * calculation in the form [x, y, theta]ᵀ, with + * units in meters and radians + * @param visionStandardDeviation The standard deviation for vision + * calculation in the form [x, y, theta]ᵀ, with + * units in meters and radians + * @param modules Constants for each specific module + */ + public CommandSwerveDrivetrain(SwerveDrivetrainConstants drivetrainConstants, double odometryUpdateFrequency, + Matrix odometryStandardDeviation, Matrix visionStandardDeviation, + SwerveModuleConstants... modules) { + super(drivetrainConstants, odometryUpdateFrequency, odometryStandardDeviation, visionStandardDeviation, + modules); + if (Utils.isSimulation()) { + startSimThread(); + } + configureAutoBuilder(); + } + + private void configureAutoBuilder() { + try { + var config = RobotConfig.fromGUISettings(); + AutoBuilder.configure(() -> getState().Pose, // Supplier of current robot pose + this::resetPose, // Consumer for seeding pose against auto + () -> getState().Speeds, // Supplier of current robot speeds + // Consumer of ChassisSpeeds and feedforwards to drive the robot + (speeds, feedforwards) -> setControl(m_pathApplyRobotSpeeds.withSpeeds(speeds) + .withWheelForceFeedforwardsX(feedforwards.robotRelativeForcesXNewtons()) + .withWheelForceFeedforwardsY(feedforwards.robotRelativeForcesYNewtons())), + new PPHolonomicDriveController( + // PID constants for translation + new PIDConstants(10, 0, 0), + // PID constants for rotation + new PIDConstants(7, 0, 0)), + config, + // Assume the path needs to be flipped for Red vs Blue, this is normally the + // case + () -> DriverStation.getAlliance().orElse(Alliance.Blue) == Alliance.Red, this // Subsystem for + // requirements + ); + } catch (Exception ex) { + DriverStation.reportError("Failed to load PathPlanner config and configure AutoBuilder", + ex.getStackTrace()); + } + } + + /** + * Returns a command that applies the specified control request to this swerve + * drivetrain. + * + * @param request Function returning the request to apply + * @return Command to run + */ + public Command applyRequest(Supplier requestSupplier) { + return run(() -> this.setControl(requestSupplier.get())); + } + + /** + * Runs the SysId Quasistatic test in the given direction for the routine + * specified by {@link #m_sysIdRoutineToApply}. + * + * @param direction Direction of the SysId Quasistatic test + * @return Command to run + */ + public Command sysIdQuasistatic(SysIdRoutine.Direction direction) { + return m_sysIdRoutineToApply.quasistatic(direction); + } + + /** + * Runs the SysId Dynamic test in the given direction for the routine specified + * by {@link #m_sysIdRoutineToApply}. + * + * @param direction Direction of the SysId Dynamic test + * @return Command to run + */ + public Command sysIdDynamic(SysIdRoutine.Direction direction) { + return m_sysIdRoutineToApply.dynamic(direction); + } + + @Override + public void periodic() { + /* + * Periodically try to apply the operator perspective. If we haven't applied the + * operator perspective before, then we should apply it regardless of DS state. + * This allows us to correct the perspective in case the robot code restarts + * mid-match. Otherwise, only check and apply the operator perspective if the DS + * is disabled. This ensures driving behavior doesn't change until an explicit + * disable event occurs during testing. + */ + if (!m_hasAppliedOperatorPerspective || DriverStation.isDisabled()) { + DriverStation.getAlliance().ifPresent(allianceColor -> { + setOperatorPerspectiveForward(allianceColor == Alliance.Red ? kRedAlliancePerspectiveRotation + : kBlueAlliancePerspectiveRotation); + m_hasAppliedOperatorPerspective = true; + }); + } + } + + private void startSimThread() { + m_lastSimTime = Utils.getCurrentTimeSeconds(); + + /* Run simulation at a faster rate so PID gains behave more reasonably */ + m_simNotifier = new Notifier(() -> { + final double currentTime = Utils.getCurrentTimeSeconds(); + double deltaTime = currentTime - m_lastSimTime; + m_lastSimTime = currentTime; + + /* use the measured time delta, get battery voltage from WPILib */ + updateSimState(deltaTime, RobotController.getBatteryVoltage()); + }); + m_simNotifier.startPeriodic(kSimLoopPeriod); + } + + /** + * Adds a vision measurement to the Kalman Filter. This will correct the + * odometry pose estimate while still accounting for measurement noise. + * + * @param visionRobotPoseMeters The pose of the robot as measured by the vision + * camera. + * @param timestampSeconds The timestamp of the vision measurement in + * seconds. + */ + @Override + public void addVisionMeasurement(Pose2d visionRobotPoseMeters, double timestampSeconds) { + super.addVisionMeasurement(visionRobotPoseMeters, Utils.fpgaToCurrentTime(timestampSeconds)); + } + + /** + * Adds a vision measurement to the Kalman Filter. This will correct the + * odometry pose estimate while still accounting for measurement noise. + *

+ * Note that the vision measurement standard deviations passed into this method + * will continue to apply to future measurements until a subsequent call to + * {@link #setVisionMeasurementStdDevs(Matrix)} or this method. + * + * @param visionRobotPoseMeters The pose of the robot as measured by the + * vision camera. + * @param timestampSeconds The timestamp of the vision measurement in + * seconds. + * @param visionMeasurementStdDevs Standard deviations of the vision pose + * measurement in the form [x, y, theta]ᵀ, with + * units in meters and radians. + */ + @Override + public void addVisionMeasurement(Pose2d visionRobotPoseMeters, double timestampSeconds, + Matrix visionMeasurementStdDevs) { + super.addVisionMeasurement(visionRobotPoseMeters, Utils.fpgaToCurrentTime(timestampSeconds), + visionMeasurementStdDevs); + } +} diff --git a/2024-2025/main-bot/src/main/java/frc/robot/subsystems/CoralArmSubsystem.java b/2024-2025/main-bot/src/main/java/frc/robot/subsystems/CoralArmSubsystem.java new file mode 100644 index 0000000..927c971 --- /dev/null +++ b/2024-2025/main-bot/src/main/java/frc/robot/subsystems/CoralArmSubsystem.java @@ -0,0 +1,97 @@ +package frc.robot.subsystems; + +//"A good programmers code needs not any comments, for it comments on itself" - IDK who I made it up +import edu.wpi.first.wpilibj2.command.SubsystemBase; +import frc.robot.Constants.CoralArmConstants; + +import java.util.function.BooleanSupplier; + +import com.ctre.phoenix.motorcontrol.ControlMode; +import com.ctre.phoenix.motorcontrol.can.TalonSRX; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj.Encoder; + +public class CoralArmSubsystem extends SubsystemBase { + // Motor(s) + private final TalonSRX m_CoralArmMotor; + // Encoder + private final Encoder m_coralEncoder; + // Current state + private CoralArmLevels currentCoralArmState; + + public CoralArmSubsystem() { + // Initialized Stuff + m_coralEncoder = new Encoder(CoralArmConstants.kCoralEncoderID1, CoralArmConstants.kCoralEncoderID2); + m_CoralArmMotor = new TalonSRX(CoralArmConstants.coralArmMotorID); + currentCoralArmState = CoralArmLevels.Down; + } + + public enum CoralArmLevels { + Down, Up, Stop + } + + public Command CommandsetCoralArmVoltage(double voltage, CoralArmLevels desiredState) { + return runOnce(() -> { + if (voltage > 0) { + if (m_coralEncoder.get() < CoralArmConstants.kCoralEncoderTopValue) { + setCoralArmVoltage(voltage); + } else if (m_coralEncoder.get() > CoralArmConstants.kCoralEncoderTopBuffer) { + System.out.println("How is the arm not broken yet? Amazingly, you didn't break it."); + setCoralArmVoltage(0); + } else { + setCoralArmVoltage(0); + currentCoralArmState = desiredState; + } + } else if (voltage < 0) { + if (m_coralEncoder.get() > CoralArmConstants.kCoralEncoderBottomValue) { + setCoralArmVoltage(voltage); + } else if (m_coralEncoder.get() < CoralArmConstants.kCoralEncoderBottomBuffer) { + System.out.println("How is the arm not broken yet? Amazingly, you didn't break it."); + setCoralArmVoltage(0); + } else { + setCoralArmVoltage(0); + currentCoralArmState = desiredState; + } + } else { + setCoralArmVoltage(0); + currentCoralArmState = desiredState; + } + }); + } + + public void setCoralArmVoltage(double voltage) { + m_CoralArmMotor.set(ControlMode.PercentOutput, voltage); + // Add more motors here if neccessary + } + + public CoralArmLevels getCurrentCoralArmState() { + return currentCoralArmState; + } + + public BooleanSupplier isCoralArmAtDesiredState(CoralArmLevels desiredState) { + return () -> currentCoralArmState == desiredState; + } + + public Command emergencyStop() {// Just in case the driver wants to stop the arm without stopping the whole + // program (and for some reason the Command Voltage function doesn't stop the + // arm after it gets above a certain point). + return runOnce(() -> { + setCoralArmVoltage(0); + System.out.println("Emergency Stop Pressed! Stay Still And Don't Move The Arm..."); + if (m_coralEncoder.get() > CoralArmConstants.kCoralEncoderTopValue) { + do {// Hey look at that, a do while loop has a use! + setCoralArmVoltage(-0.25); + } while (m_coralEncoder.get() > CoralArmConstants.kCoralEncoderTopValue); + setCoralArmVoltage(0); + } else if (m_coralEncoder.get() < CoralArmConstants.kCoralEncoderTopValue) { + do { + setCoralArmVoltage(0.25); + } while (m_coralEncoder.get() < CoralArmConstants.kCoralEncoderTopValue); + setCoralArmVoltage(0); + } else { + System.out.println("Arm is already at top"); + } + System.out.println("Arm Is Now Reset. Carry On."); + }); + } +} diff --git a/2024-2025/main-bot/src/main/java/frc/robot/subsystems/ElevatorSubsystem.java b/2024-2025/main-bot/src/main/java/frc/robot/subsystems/ElevatorSubsystem.java new file mode 100644 index 0000000..add87d4 --- /dev/null +++ b/2024-2025/main-bot/src/main/java/frc/robot/subsystems/ElevatorSubsystem.java @@ -0,0 +1,229 @@ +package frc.robot.subsystems; + +import edu.wpi.first.wpilibj2.command.SubsystemBase; +import edu.wpi.first.wpilibj.DigitalInput; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.FunctionalCommand; +import edu.wpi.first.wpilibj.Encoder; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; +import frc.robot.Logging; +import frc.robot.Robot; +import frc.robot.RobotContainer; +import frc.robot.Constants.ElevatorConstants; + +import java.util.function.BooleanSupplier; + +//import com.ctre.phoenix.Util; +import com.ctre.phoenix6.hardware.TalonFX; +import frc.robot.Utility; + +public class ElevatorSubsystem extends SubsystemBase {// makes elevator subsystem into an actual subsystem + private final Logging elevatorLogger; + // Motors + private final TalonFX m_elevatorLeftMotor; + private final TalonFX m_elevatorRightMotor; + // Limit Switches + private DigitalInput m_elevatorTopLimitSwitch; + private DigitalInput m_elevatorBottomLimitSwitch; + // Encoder + private final Encoder m_leftElevatorEncoder; + private final Encoder m_rightElevatorEncoder; + private ElevatorPresets currentElevatorState; + // Constants + private double motorElevatorSpeed; // Might take out in favor of motion magic + private final double elevatorEncoderTopValue; + private final double elevatorEncoderBottomValue; + private final double preset1EncoderValue; + private final double preset2EncoderValue; + private final double preset3EncoderValue; + private final double preset4EncoderValue; + + public ElevatorSubsystem() {// constructor for the elevator subsystem + // Motor Initialization + m_elevatorLeftMotor = new TalonFX(ElevatorConstants.kElevatorLeftMotorID); + m_elevatorRightMotor = new TalonFX(ElevatorConstants.kElevatorRightMotorID); + // Limit Switch Initialization + m_elevatorTopLimitSwitch = new DigitalInput(7); + m_elevatorBottomLimitSwitch = new DigitalInput(8); + // Encoder Initialization + m_leftElevatorEncoder = new Encoder(ElevatorConstants.kLeftElevatorEncoderID1, + ElevatorConstants.kLeftElevatorEncoderID2); + m_rightElevatorEncoder = new Encoder(ElevatorConstants.kRightElevatorEncoderID1, + ElevatorConstants.kRightElevatorEncoderID2); + // Current State Initialization + currentElevatorState = ElevatorPresets.Level1; + elevatorLogger = new Logging("ElevatorSubsystem"); + // Constants Initialization + motorElevatorSpeed = ElevatorConstants.kMotorElevatorSpeed; + elevatorEncoderTopValue = ElevatorConstants.kElevatorEncoderTopValue; + elevatorEncoderBottomValue = ElevatorConstants.kElevatorEncoderBottomValue; + preset1EncoderValue = ElevatorConstants.ElevatorPreset.level1EncoderValue; + preset2EncoderValue = ElevatorConstants.ElevatorPreset.level2EncoderValue; + preset3EncoderValue = ElevatorConstants.ElevatorPreset.level3EncoderValue; + preset4EncoderValue = ElevatorConstants.ElevatorPreset.level4EncoderValue; + } + + public enum ElevatorPresets { // different levels for the coral reef + Level1, Level2, Level3, Level4 + } + + // public Command raiseElevator() { + // // Placeholder + // return runOnce(() -> { + // /* one-time action goes here */ + // setMotorElevatorSpeed(0.1); + // }); + // } + + // public Command lowerElevator() { + // // Placeholder + // return runOnce(() -> { + // /* one-time action goes here */ + // setMotorElevatorSpeed(-0.1); + // }); + // } + + public void debuggingMethod() { + SmartDashboard.putNumber("Elevator Encoder", m_leftElevatorEncoder.get()); + SmartDashboard.putBoolean("Elevator Top Limit Switch", m_elevatorTopLimitSwitch.get()); + SmartDashboard.putBoolean("Elevator Bottom Limit Switch", m_elevatorBottomLimitSwitch.get()); + } + + public boolean isElevatorAtTop() { + // Placeholder + if (m_leftElevatorEncoder.get() <= elevatorEncoderTopValue && !m_elevatorTopLimitSwitch.get()) { + return false; + } else if (m_leftElevatorEncoder.get() <= elevatorEncoderBottomValue || !m_elevatorTopLimitSwitch.get()) { + // System.out.println("Error: Encoder And Top Limit Switch Mismatched"); + elevatorLogger.error("Encoder And Top Limit Switch Mismatched"); + return true; + } else { + return true; + } + } + + public boolean isElevatorAtBottom() { + // Placeholder + if (m_leftElevatorEncoder.get() >= elevatorEncoderBottomValue && !m_elevatorBottomLimitSwitch.get()) { + return false; + } else if (m_leftElevatorEncoder.get() >= elevatorEncoderBottomValue || !m_elevatorBottomLimitSwitch.get()) { + // System.out.println("Error: Encoder And Bottom Limit Switch Mismatched"); + elevatorLogger.error("Encoder And Bottom Limit Switch Mismatched"); + return true; + } else { + return true; + } + } + + public void setMotorElevatorSpeed(boolean isGoingup) { + // Placeholder + debuggingMethod(); + if (isGoingup && !isElevatorAtTop()) {// if motor is moving and elevators at the top, make both move up + m_elevatorLeftMotor.set(motorElevatorSpeed); + m_elevatorRightMotor.set(-motorElevatorSpeed); + Utility.printLn("Elevator is moving up"); + } else if (!isGoingup && !isElevatorAtBottom()) {// or if its at bottom make move down + m_elevatorLeftMotor.set(-motorElevatorSpeed); + m_elevatorRightMotor.set(-motorElevatorSpeed); + Utility.printLn("Elevator is moving down"); + } else {// otherwise just no speed + m_elevatorLeftMotor.set(0); + m_elevatorRightMotor.set(0); + System.out.println("Motor Voltage Value: " + m_elevatorLeftMotor.getMotorVoltage() + + "\n desired Voltage Value: " + motorElevatorSpeed + "\n is elevator going up: " + isGoingup + + "\n Elevator Encoder Value: " + m_leftElevatorEncoder.get() + + "\n Elevator Top Limit Switch Value: " + m_elevatorTopLimitSwitch.get() + + "\n Elevator Bottom Limit Switch Value: " + m_elevatorBottomLimitSwitch.get()); + Utility.printLn("Elevator is at the top, bottom, or desired position. motors have been stopped"); + } + } + + public void moveElevatorToPreset(ElevatorPresets desiredPreset) {// tells elevator where to go based on certain + // presets using distgusting switch case statements + switch (desiredPreset) { + case Level1: + SmartDashboard.putString("DesiredPreset", "Level1"); + moveElevatorToSpecificPreset(preset1EncoderValue, desiredPreset); + break; + case Level2: + SmartDashboard.putString("DesiredPreset", "Level2"); + moveElevatorToSpecificPreset(preset2EncoderValue, desiredPreset); + break; + case Level3: + SmartDashboard.putString("DesiredPreset", "Level3"); + moveElevatorToSpecificPreset(preset3EncoderValue, desiredPreset); + break; + case Level4: + SmartDashboard.putString("DesiredPreset", "Level4"); + moveElevatorToSpecificPreset(preset4EncoderValue, desiredPreset); + break; + } + } + + /** + * The moveElevatorToPosition method takes a double as a parameter. This value + * represents the number of rotations necessary to reach the target position. + * + * fun fact: 6!! is 6 * 4 * 2 while 7!! is 7 * 5 * 3 * 1. Kind of like a + * selective factorial. Yeah idk why I said that. Moving on + * + * Oooooo thats a really fun fact! I didn't know you could have selective + * factorials! - H + * + * @param position + * @param desiredPreset + */ + public void moveElevatorToSpecificPreset(double position, ElevatorPresets desiredPreset) {// moves elevator to a + // certain + // position based on the encoder + // value + // WILL HAVE TO REVERSE ONE MOTOR DEPENDING ON ORIENTATION!!!! + debuggingMethod(); + if (m_leftElevatorEncoder.get() <= (position + 5) && !isElevatorAtBottom()) { // checking to see if the motor + // wants to move + // down and makes sure the elevator isn't at + // the bottom + m_elevatorLeftMotor.set(-motorElevatorSpeed); + m_elevatorRightMotor.set(motorElevatorSpeed); + Utility.printLn("Elevator is moving down"); + } else if (m_leftElevatorEncoder.get() >= (position - 5) && !isElevatorAtTop()) { // checking to see if the + // motor wants to + // move up and makes sure the elevator + // isn't at the top + m_elevatorLeftMotor.set(motorElevatorSpeed); + m_elevatorRightMotor.set(-motorElevatorSpeed); + Utility.printLn("Elevator is moving up"); + } else { + m_elevatorLeftMotor.set(0); + m_elevatorRightMotor.set(0); + Utility.printLn( + "Elevator is at the top, bottom, desired position, or error occurred and therefore the motors have been stopped"); + currentElevatorState = desiredPreset; + } + } + + public ElevatorPresets getElevatorState() { + return currentElevatorState; + } + + public BooleanSupplier isElevatorAtDesiredState(ElevatorPresets desiredState) { + return () -> currentElevatorState == desiredState; + } + + // public Command commandVoltage(double voltage) {// just exists because just + // felt like it + // return runOnce(() -> { + // setMotorElevatorSpeed(voltage); + // }); + // } + + public Command commandMoveToPreset(ElevatorPresets desiredPreset) {// The first function in a very tall dependancy + // tree + return runOnce(() -> { + moveElevatorToPreset(desiredPreset); + }); + } + +} +// a comment because why not :) +// This is a very cool comment *wink* *wink* *nudge* *nudge* diff --git a/2024-2025/main-bot/src/main/java/frc/robot/subsystems/LimeLightSubsystem.java b/2024-2025/main-bot/src/main/java/frc/robot/subsystems/LimeLightSubsystem.java new file mode 100644 index 0000000..b0c8f26 --- /dev/null +++ b/2024-2025/main-bot/src/main/java/frc/robot/subsystems/LimeLightSubsystem.java @@ -0,0 +1,164 @@ +package frc.robot.subsystems; + +import edu.wpi.first.math.MathUtil; +import edu.wpi.first.math.VecBuilder; +import edu.wpi.first.math.estimator.PoseEstimator; +import edu.wpi.first.math.estimator.SwerveDrivePoseEstimator; +import edu.wpi.first.math.geometry.Pose2d; +import edu.wpi.first.math.kinematics.SwerveModulePosition; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.SubsystemBase; +import frc.robot.Constants.DriveTrainConstants; +import frc.robot.LimelightHelpers; +// import edu.first.LimelightHelpers; +// import edu.first.wpilibj. + +// bunch of random imports + +import edu.wpi.first.math.kinematics.SwerveDriveKinematics; + +import edu.wpi.first.math.util.Units; +import edu.wpi.first.wpilibj.AnalogGyro; +import edu.wpi.first.wpilibj.DriverStation; +import edu.wpi.first.wpilibj.Timer; +import edu.wpi.first.wpilibj.DriverStation.Alliance; + +public class LimeLightSubsystem extends SubsystemBase { + + /** + * tx - Horizontal Offset ty - Vertical Offset ta - Area of target tv - Target + * Visible + */ + + int FLIndex = 0; + int FRIndex = 1; + int BLIndex = 2; + int BRIndex = 3; + + private final SwerveDrivePoseEstimator m_poseEstimator; + + public LimeLightSubsystem(CommandSwerveDrivetrain swerveDriveTrain) { + + m_poseEstimator = new SwerveDrivePoseEstimator(swerveDriveTrain.getKinematics(), + swerveDriveTrain.getPigeon2().getRotation2d(), + new SwerveModulePosition[] { swerveDriveTrain.getModule(0).getPosition(true), + swerveDriveTrain.getModule(1).getPosition(true), swerveDriveTrain.getModule(2).getPosition(true), + swerveDriveTrain.getModule(3).getPosition(true) }, + new Pose2d(), VecBuilder.fill(0.05, 0.05, Units.degreesToRadians(5)), + VecBuilder.fill(0.5, 0.5, Units.degreesToRadians(30))); + } + + public void updateOdometry(CommandSwerveDrivetrain swerveDriveTrain) { + + m_poseEstimator.update(swerveDriveTrain.getPigeon2().getRotation2d(), + new SwerveModulePosition[] { swerveDriveTrain.getModule(0).getPosition(true), + swerveDriveTrain.getModule(1).getPosition(true), swerveDriveTrain.getModule(2).getPosition(true), + swerveDriveTrain.getModule(3).getPosition(true) }); + + // Is this boolean ever changing at runtime? If not, it should be a final + // variable + boolean useMegaTag2 = true; // set to false to use MegaTag1 + boolean doRejectUpdate = false; + if (useMegaTag2 == false) { + // Use this line to know whether we are part of an alliance (we might not be if + // we are not in a match presently) + // DriverStation.getAlliance().isEmpty() + + // Use this line to know whether we are on the blue alliance + // DriverStation.getAlliance().get().equals(Alliance.Blue); + + // This should change depending on the alliance we are on + LimelightHelpers.PoseEstimate mt1 = LimelightHelpers.getBotPoseEstimate_wpiBlue("limelight"); + + if (mt1.tagCount == 1 && mt1.rawFiducials.length == 1) { + if (mt1.rawFiducials[0].ambiguity > .7) { + doRejectUpdate = true; + } + if (mt1.rawFiducials[0].distToCamera > 3) { + doRejectUpdate = true; + } + } + if (mt1.tagCount == 0) { + doRejectUpdate = true; + } + + if (!doRejectUpdate) { + m_poseEstimator.setVisionMeasurementStdDevs(VecBuilder.fill(.5, .5, 9999999)); + m_poseEstimator.addVisionMeasurement(mt1.pose, mt1.timestampSeconds); + + swerveDriveTrain.addVisionMeasurement(mt1.pose, mt1.timestampSeconds, VecBuilder.fill(.5, .5, 9999999)); + } + } else if (useMegaTag2 == true) { + LimelightHelpers.SetRobotOrientation("limelight", + m_poseEstimator.getEstimatedPosition().getRotation().getDegrees(), 0, 0, 0, 0, 0); + + // Same thing as above + LimelightHelpers.PoseEstimate mt2 = LimelightHelpers.getBotPoseEstimate_wpiBlue_MegaTag2("limelight"); + // NOTE! The .getAngularVelocityZWorld() update is different from orignal code. + // The method .getRate() is depreicated and will be removed soom, so we have + // switched to this method. However, it is CCW+ instead of CW+, and may not + // return the same value + if (Math.abs(swerveDriveTrain.getPigeon2().getAngularVelocityZWorld().getValueAsDouble()) > 720) + // if our angular velocity is greater than 720 degrees per second, ignore vision + // updates + { + doRejectUpdate = true; + } + if (mt2.tagCount == 0) { + doRejectUpdate = true; + } + if (!doRejectUpdate) { + m_poseEstimator.setVisionMeasurementStdDevs(VecBuilder.fill(.7, .7, 9999999)); + m_poseEstimator.addVisionMeasurement(mt2.pose, mt2.timestampSeconds); + + swerveDriveTrain.addVisionMeasurement(mt2.pose, mt2.timestampSeconds, VecBuilder.fill(.7, .7, 9999999)); + } + } + } + + public PoseEstimator getPoseEstimator() { + return m_poseEstimator; + } + + /** + * simple proportional turning control with Limelight. "proportional control" is + * a control algorithm in which the output is proportional to the error. in this + * case, we are going to return an angular velocity that is proportional to the + * "tx" value from the Limelight. + */ + public double limelight_aim_proportional() { + // kP (constant of proportionality) + // this is a hand-tuned number that determines the aggressiveness of our + // proportional control loop + // if it is too high, the robot will oscillate around. + // if it is too low, the robot will never reach its target + // if the robot never turns in the correct direction, kP should be inverted. + double kP = .035; + + // tx ranges from (-hfov/2) to (hfov/2) in degrees. If your target is on the + // rightmost edge of your limelight 3 feed, tx should return roughly 31 degrees. + double targetingAngularVelocity = LimelightHelpers.getTX("DriveCamera") * kP; + + // convert to radians per second for our drive method + targetingAngularVelocity *= DriveTrainConstants.MaxAngularRate; + + // invert since tx is positive when the target is to the right of the crosshair + targetingAngularVelocity *= -1.0; + + return targetingAngularVelocity; + } + + /** + * simple proportional ranging control with Limelight's "ty" value this works + * best if your Limelight's mount height and target mount height are different. + * if your limelight and target are mounted at the same or similar heights, use + * "ta" (area) for target ranging rather than "ty" + */ + public double limelight_range_proportional() { + double kP = .1; + double targetingForwardSpeed = LimelightHelpers.getTY("limelight") * kP; + targetingForwardSpeed *= DriveTrainConstants.MaxSpeed; + targetingForwardSpeed *= -1.0; + return targetingForwardSpeed; + } +} diff --git a/2024-2025/main-bot/src/main/java/frc/robot/subsystems/MapleSimSubsystem.java b/2024-2025/main-bot/src/main/java/frc/robot/subsystems/MapleSimSubsystem.java new file mode 100644 index 0000000..03d55ef --- /dev/null +++ b/2024-2025/main-bot/src/main/java/frc/robot/subsystems/MapleSimSubsystem.java @@ -0,0 +1,54 @@ +package frc.robot.subsystems; + +import org.ironmaple.simulation.SimulatedArena; +import org.ironmaple.simulation.drivesims.COTS; +import org.ironmaple.simulation.drivesims.configs.DriveTrainSimulationConfig; +import org.ironmaple.simulation.seasonspecific.crescendo2024.CrescendoNoteOnField; + +import com.ctre.phoenix6.swerve.SwerveDrivetrain; +import static edu.wpi.first.units.Units.*; + +import edu.wpi.first.math.geometry.Translation2d; +import edu.wpi.first.math.system.plant.DCMotor; +import edu.wpi.first.wpilibj2.command.SubsystemBase; + +import frc.robot.Constants.DriveTrainConstants;; + +public class MapleSimSubsystem extends SubsystemBase { + + private DriveTrainSimulationConfig driveTrainSimulationConfig; + + public MapleSimSubsystem(CommandSwerveDrivetrain drivetrain) { + // Placeholder + + // Obtains the default instance of the simulation world, which is a Crescendo + // Arena. + // SimulatedArena.getInstance(); + // Overrides the default simulation (isn't supported right now) + // SimulatedArena.overrideInstance(SimulatedArena newInstance); + + // Create and configure a drivetrain simulation configuration + driveTrainSimulationConfig = DriveTrainSimulationConfig.Default() + // Specify gyro type (for realistic gyro drifting and error simulation) + .withGyro(COTS.ofPigeon2()) + // Specify swerve module (for realistic swerve dynamics) + .withSwerveModule(COTS.ofSwerveXFlipped(DCMotor.getKrakenX60(1), // Drive motor is a Kraken X60 + DCMotor.getKrakenX60(1), // Steer motor is a Kraken + COTS.WHEELS.DEFAULT_NEOPRENE_TREAD.cof, // Use the COF for Neoprene Wheels + 9)) // L3 Gear ratio + // Configures the track length and track width (spacing between swerve modules) + .withTrackLengthTrackWidth(Inches.of(DriveTrainConstants.lengthBetweenSwerveModules), + Inches.of(DriveTrainConstants.lengthBetweenSwerveModules)) + // Configures the bumper size (dimensions of the robot bumper) + .withBumperSize(Inches.of(DriveTrainConstants.lengthOfBumpers), + Inches.of(DriveTrainConstants.lengthOfBumpers)); + } + + public void addGamePiece() { + SimulatedArena.getInstance().addGamePiece(new CrescendoNoteOnField(new Translation2d(3, 3))); + } + + public void clearGamePieces() { + SimulatedArena.getInstance().clearGamePieces(); + } +} diff --git a/2024-2025/main-bot/vendordeps/AdvantageKit.json b/2024-2025/main-bot/vendordeps/AdvantageKit.json new file mode 100644 index 0000000..03df051 --- /dev/null +++ b/2024-2025/main-bot/vendordeps/AdvantageKit.json @@ -0,0 +1,35 @@ +{ + "fileName": "AdvantageKit.json", + "name": "AdvantageKit", + "version": "4.1.0", + "uuid": "d820cc26-74e3-11ec-90d6-0242ac120003", + "frcYear": "2025", + "mavenUrls": [ + "https://frcmaven.wpi.edu/artifactory/littletonrobotics-mvn-release/" + ], + "jsonUrl": "https://github.com/Mechanical-Advantage/AdvantageKit/releases/latest/download/AdvantageKit.json", + "javaDependencies": [ + { + "groupId": "org.littletonrobotics.akit", + "artifactId": "akit-java", + "version": "4.1.0" + } + ], + "jniDependencies": [ + { + "groupId": "org.littletonrobotics.akit", + "artifactId": "akit-wpilibio", + "version": "4.1.0", + "skipInvalidPlatforms": false, + "isJar": false, + "validPlatforms": [ + "linuxathena", + "linuxx86-64", + "linuxarm64", + "osxuniversal", + "windowsx86-64" + ] + } + ], + "cppDependencies": [] +} \ No newline at end of file diff --git a/2024-2025/main-bot/vendordeps/PathplannerLib-2025.2.3.json b/2024-2025/main-bot/vendordeps/PathplannerLib-2025.2.3.json new file mode 100644 index 0000000..9151ce4 --- /dev/null +++ b/2024-2025/main-bot/vendordeps/PathplannerLib-2025.2.3.json @@ -0,0 +1,38 @@ +{ + "fileName": "PathplannerLib-2025.2.3.json", + "name": "PathplannerLib", + "version": "2025.2.3", + "uuid": "1b42324f-17c6-4875-8e77-1c312bc8c786", + "frcYear": "2025", + "mavenUrls": [ + "https://3015rangerrobotics.github.io/pathplannerlib/repo" + ], + "jsonUrl": "https://3015rangerrobotics.github.io/pathplannerlib/PathplannerLib.json", + "javaDependencies": [ + { + "groupId": "com.pathplanner.lib", + "artifactId": "PathplannerLib-java", + "version": "2025.2.3" + } + ], + "jniDependencies": [], + "cppDependencies": [ + { + "groupId": "com.pathplanner.lib", + "artifactId": "PathplannerLib-cpp", + "version": "2025.2.3", + "libName": "PathplannerLib", + "headerClassifier": "headers", + "sharedLibrary": false, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal", + "linuxathena", + "linuxarm32", + "linuxarm64" + ] + } + ] +} \ No newline at end of file diff --git a/2024-2025/main-bot/vendordeps/Phoenix5-replay-5.35.1.json b/2024-2025/main-bot/vendordeps/Phoenix5-replay-5.35.1.json new file mode 100644 index 0000000..bdf2f44 --- /dev/null +++ b/2024-2025/main-bot/vendordeps/Phoenix5-replay-5.35.1.json @@ -0,0 +1,221 @@ +{ + "fileName": "Phoenix5-replay-5.35.1.json", + "name": "CTRE-Phoenix (v5)", + "version": "5.35.1", + "frcYear": "2025", + "uuid": "fbc886a4-2cec-40c0-9835-71086a8cc3df", + "mavenUrls": [ + "https://maven.ctr-electronics.com/release/" + ], + "jsonUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix/Phoenix5-replay-frc2025-latest.json", + "requires": [ + { + "uuid": "e7900d8d-826f-4dca-a1ff-182f658e98af", + "errorMessage": "Phoenix 5 requires low-level libraries from Phoenix 6. Please add the Phoenix 6 vendordep before adding Phoenix 5.", + "offlineFileName": "Phoenix6-replay-frc2025-latest.json", + "onlineUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix6/latest/Phoenix6-replay-frc2025-latest.json" + } + ], + "conflictsWith": [ + { + "uuid": "e995de00-2c64-4df5-8831-c1441420ff19", + "errorMessage": "Users must use the regular Phoenix 5 vendordep when using the regular Phoenix 6 vendordep.", + "offlineFileName": "Phoenix6-frc2025-latest.json" + }, + { + "uuid": "ab676553-b602-441f-a38d-f1296eff6537", + "errorMessage": "Users cannot have both the replay and regular Phoenix 5 vendordeps in their robot program.", + "offlineFileName": "Phoenix5-frc2025-latest.json" + } + ], + "javaDependencies": [ + { + "groupId": "com.ctre.phoenix", + "artifactId": "api-java", + "version": "5.35.1" + }, + { + "groupId": "com.ctre.phoenix", + "artifactId": "wpiapi-java", + "version": "5.35.1" + } + ], + "jniDependencies": [ + { + "groupId": "com.ctre.phoenix", + "artifactId": "cci", + "version": "5.35.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix.replay", + "artifactId": "cci-replay", + "version": "5.35.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "cci-sim", + "version": "5.35.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + } + ], + "cppDependencies": [ + { + "groupId": "com.ctre.phoenix", + "artifactId": "wpiapi-cpp", + "version": "5.35.1", + "libName": "CTRE_Phoenix_WPI", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix", + "artifactId": "api-cpp", + "version": "5.35.1", + "libName": "CTRE_Phoenix", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix", + "artifactId": "cci", + "version": "5.35.1", + "libName": "CTRE_PhoenixCCI", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix.replay", + "artifactId": "wpiapi-cpp-replay", + "version": "5.35.1", + "libName": "CTRE_Phoenix_WPIReplay", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix.replay", + "artifactId": "api-cpp-replay", + "version": "5.35.1", + "libName": "CTRE_PhoenixReplay", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix.replay", + "artifactId": "cci-replay", + "version": "5.35.1", + "libName": "CTRE_PhoenixCCIReplay", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "wpiapi-cpp-sim", + "version": "5.35.1", + "libName": "CTRE_Phoenix_WPISim", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "api-cpp-sim", + "version": "5.35.1", + "libName": "CTRE_PhoenixSim", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "cci-sim", + "version": "5.35.1", + "libName": "CTRE_PhoenixCCISim", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + } + ] +} \ No newline at end of file diff --git a/2024-2025/main-bot/vendordeps/Phoenix6-replay-25.2.1.json b/2024-2025/main-bot/vendordeps/Phoenix6-replay-25.2.1.json new file mode 100644 index 0000000..77acc5a --- /dev/null +++ b/2024-2025/main-bot/vendordeps/Phoenix6-replay-25.2.1.json @@ -0,0 +1,467 @@ +{ + "fileName": "Phoenix6-replay-25.2.1.json", + "name": "CTRE-Phoenix (v6) Replay", + "version": "25.2.1", + "frcYear": "2025", + "uuid": "e7900d8d-826f-4dca-a1ff-182f658e98af", + "mavenUrls": [ + "https://maven.ctr-electronics.com/release/" + ], + "jsonUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix6/latest/Phoenix6-replay-frc2025-latest.json", + "conflictsWith": [ + { + "uuid": "e995de00-2c64-4df5-8831-c1441420ff19", + "errorMessage": "Users can not have both the replay and regular Phoenix 6 vendordeps in their robot program.", + "offlineFileName": "Phoenix6-frc2025-latest.json" + } + ], + "javaDependencies": [ + { + "groupId": "com.ctre.phoenix6", + "artifactId": "wpiapi-java", + "version": "25.2.1" + } + ], + "jniDependencies": [ + { + "groupId": "com.ctre.phoenix6", + "artifactId": "api-cpp", + "version": "25.2.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6", + "artifactId": "tools", + "version": "25.2.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6.replay", + "artifactId": "api-cpp-replay", + "version": "25.2.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6.replay", + "artifactId": "tools-replay", + "version": "25.2.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "api-cpp-sim", + "version": "25.2.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "tools-sim", + "version": "25.2.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simTalonSRX", + "version": "25.2.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simVictorSPX", + "version": "25.2.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simPigeonIMU", + "version": "25.2.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simCANCoder", + "version": "25.2.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProTalonFX", + "version": "25.2.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProTalonFXS", + "version": "25.2.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANcoder", + "version": "25.2.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProPigeon2", + "version": "25.2.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANrange", + "version": "25.2.1", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + } + ], + "cppDependencies": [ + { + "groupId": "com.ctre.phoenix6", + "artifactId": "wpiapi-cpp", + "version": "25.2.1", + "libName": "CTRE_Phoenix6_WPI", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6", + "artifactId": "tools", + "version": "25.2.1", + "libName": "CTRE_PhoenixTools", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6.replay", + "artifactId": "wpiapi-cpp-replay", + "version": "25.2.1", + "libName": "CTRE_Phoenix6_WPIReplay", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6.replay", + "artifactId": "tools-replay", + "version": "25.2.1", + "libName": "CTRE_PhoenixTools_Replay", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "wpiapi-cpp-sim", + "version": "25.2.1", + "libName": "CTRE_Phoenix6_WPISim", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "tools-sim", + "version": "25.2.1", + "libName": "CTRE_PhoenixTools_Sim", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simTalonSRX", + "version": "25.2.1", + "libName": "CTRE_SimTalonSRX", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simVictorSPX", + "version": "25.2.1", + "libName": "CTRE_SimVictorSPX", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simPigeonIMU", + "version": "25.2.1", + "libName": "CTRE_SimPigeonIMU", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simCANCoder", + "version": "25.2.1", + "libName": "CTRE_SimCANCoder", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProTalonFX", + "version": "25.2.1", + "libName": "CTRE_SimProTalonFX", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProTalonFXS", + "version": "25.2.1", + "libName": "CTRE_SimProTalonFXS", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANcoder", + "version": "25.2.1", + "libName": "CTRE_SimProCANcoder", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProPigeon2", + "version": "25.2.1", + "libName": "CTRE_SimProPigeon2", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix6.sim", + "artifactId": "simProCANrange", + "version": "25.2.1", + "libName": "CTRE_SimProCANrange", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxarm64", + "osxuniversal" + ], + "simMode": "swsim" + } + ] +} \ No newline at end of file diff --git a/2024-2025/main-bot/vendordeps/Studica-2025.0.1.json b/2024-2025/main-bot/vendordeps/Studica-2025.0.1.json new file mode 100644 index 0000000..5010be0 --- /dev/null +++ b/2024-2025/main-bot/vendordeps/Studica-2025.0.1.json @@ -0,0 +1,71 @@ +{ + "fileName": "Studica-2025.0.1.json", + "name": "Studica", + "version": "2025.0.1", + "uuid": "cb311d09-36e9-4143-a032-55bb2b94443b", + "frcYear": "2025", + "mavenUrls": [ + "https://dev.studica.com/maven/release/2025/" + ], + "jsonUrl": "https://dev.studica.com/releases/2025/Studica-2025.0.1.json", + "cppDependencies": [ + { + "artifactId": "Studica-cpp", + "binaryPlatforms": [ + "linuxathena", + "linuxarm32", + "linuxarm64", + "linuxx86-64", + "osxuniversal", + "windowsx86-64" + ], + "groupId": "com.studica.frc", + "headerClassifier": "headers", + "libName": "Studica", + "sharedLibrary": false, + "skipInvalidPlatforms": true, + "version": "2025.0.1" + }, + { + "artifactId": "Studica-driver", + "binaryPlatforms": [ + "linuxathena", + "linuxarm32", + "linuxarm64", + "linuxx86-64", + "osxuniversal", + "windowsx86-64" + ], + "groupId": "com.studica.frc", + "headerClassifier": "headers", + "libName": "StudicaDriver", + "sharedLibrary": false, + "skipInvalidPlatforms": true, + "version": "2025.0.1" + } + ], + "javaDependencies": [ + { + "artifactId": "Studica-java", + "groupId": "com.studica.frc", + "version": "2025.0.1" + } + ], + "jniDependencies": [ + { + "artifactId": "Studica-driver", + "groupId": "com.studica.frc", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "linuxathena", + "linuxarm32", + "linuxarm64", + "linuxx86-64", + "osxuniversal", + "windowsx86-64" + ], + "version": "2025.0.1" + } + ] +} \ No newline at end of file diff --git a/2024-2025/main-bot/vendordeps/WPILibNewCommands.json b/2024-2025/main-bot/vendordeps/WPILibNewCommands.json new file mode 100644 index 0000000..3718e0a --- /dev/null +++ b/2024-2025/main-bot/vendordeps/WPILibNewCommands.json @@ -0,0 +1,38 @@ +{ + "fileName": "WPILibNewCommands.json", + "name": "WPILib-New-Commands", + "version": "1.0.0", + "uuid": "111e20f7-815e-48f8-9dd6-e675ce75b266", + "frcYear": "2025", + "mavenUrls": [], + "jsonUrl": "", + "javaDependencies": [ + { + "groupId": "edu.wpi.first.wpilibNewCommands", + "artifactId": "wpilibNewCommands-java", + "version": "wpilib" + } + ], + "jniDependencies": [], + "cppDependencies": [ + { + "groupId": "edu.wpi.first.wpilibNewCommands", + "artifactId": "wpilibNewCommands-cpp", + "version": "wpilib", + "libName": "wpilibNewCommands", + "headerClassifier": "headers", + "sourcesClassifier": "sources", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena", + "linuxarm32", + "linuxarm64", + "windowsx86-64", + "windowsx86", + "linuxx86-64", + "osxuniversal" + ] + } + ] +} diff --git a/2024-2025/main-bot/vendordeps/maple-sim.json b/2024-2025/main-bot/vendordeps/maple-sim.json new file mode 100644 index 0000000..579c260 --- /dev/null +++ b/2024-2025/main-bot/vendordeps/maple-sim.json @@ -0,0 +1,26 @@ +{ + "fileName": "maple-sim.json", + "name": "maplesim", + "version": "0.3.8", + "frcYear": "2025", + "uuid": "c39481e8-4a63-4a4c-9df6-48d91e4da37b", + "mavenUrls": [ + "https://shenzhen-robotics-alliance.github.io/maple-sim/vendordep/repos/releases", + "https://repo1.maven.org/maven2" + ], + "jsonUrl": "https://shenzhen-robotics-alliance.github.io/maple-sim/vendordep/maple-sim.json", + "javaDependencies": [ + { + "groupId": "org.ironmaple", + "artifactId": "maplesim-java", + "version": "0.3.8" + }, + { + "groupId": "org.dyn4j", + "artifactId": "dyn4j", + "version": "5.0.2" + } + ], + "jniDependencies": [], + "cppDependencies": [] +} \ No newline at end of file diff --git a/Example_Project/gradle/wrapper/gradle-wrapper.jar b/Example_Project/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 249e583..0000000 Binary files a/Example_Project/gradle/wrapper/gradle-wrapper.jar and /dev/null differ