From 71563e67595ca9bd04e42effa6296f6e5fb82505 Mon Sep 17 00:00:00 2001 From: nathanrsxtn Date: Tue, 11 Jan 2022 11:05:52 -0700 Subject: [PATCH] Upgrade to 2022 * Update license * Remove arcade drive * Correct indentation * Disable RobotGyro (new gyro is untested) --- .gitignore | 9 +- .templates/SubsystemTest.java | 9 +- .templates/UtilityTest.java | 9 +- .vscode/settings.json | 18 +- .wpilib/wpilib_preferences.json | 2 +- LICENSE | 24 -- README.md | 2 - WPILib-License.md | 24 ++ build.gradle | 88 ++--- gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 59536 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 269 +++++++++------ gradlew.bat | 25 +- settings.gradle | 2 +- src/main/java/frc4388/robot/Constants.java | 106 +++--- src/main/java/frc4388/robot/Robot.java | 16 +- .../java/frc4388/robot/RobotContainer.java | 175 +++++----- src/main/java/frc4388/robot/RobotMap.java | 184 ++++------- .../frc4388/robot/subsystems/ArcadeDrive.java | 85 ----- .../java/frc4388/robot/subsystems/LED.java | 2 +- .../frc4388/robot/subsystems/SwerveDrive.java | 307 ++++++++--------- .../robot/subsystems/SwerveModule.java | 47 ++- src/main/java/frc4388/utility/Gains.java | 98 +++--- src/main/java/frc4388/utility/RobotGyro.java | 180 ---------- .../java/frc4388/utility/RobotGyro.java.old | 245 ++++++++++++++ src/main/java/frc4388/utility/RobotTime.java | 109 +++--- .../utility/controller/IHandController.java | 16 +- .../utility/controller/XboxController.java | 312 +++++++++--------- .../utility/controller/XboxTriggerButton.java | 91 ++--- .../java/frc4388/mocks/MockPigeonIMU.java | 73 ++-- .../robot/subsystems/LEDSubsystemTest.java | 65 ++-- ...est.java => RobotGyroUtilityTest.java.old} | 9 +- .../frc4388/utility/RobotTimeUtilityTest.java | 153 +++++---- template.config.js | 31 -- vendordeps/Phoenix.json | 213 +++++++----- vendordeps/WPILibNewCommands.json | 3 +- vendordeps/WPILibOldCommands.json | 37 +++ vendordeps/navx_frc.json | 8 +- 38 files changed, 1507 insertions(+), 1541 deletions(-) delete mode 100644 LICENSE delete mode 100644 README.md create mode 100644 WPILib-License.md mode change 100644 => 100755 gradlew delete mode 100644 src/main/java/frc4388/robot/subsystems/ArcadeDrive.java delete mode 100644 src/main/java/frc4388/utility/RobotGyro.java create mode 100644 src/main/java/frc4388/utility/RobotGyro.java.old rename src/test/java/frc4388/utility/{RobotGyroUtilityTest.java => RobotGyroUtilityTest.java.old} (91%) delete mode 100644 template.config.js create mode 100644 vendordeps/WPILibOldCommands.json diff --git a/.gitignore b/.gitignore index 983678a..9535c83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ -# Created by https://www.gitignore.io/api/c++,java,linux,macos,gradle,windows,visualstudiocode +# This gitignore has been specially created by the WPILib team. +# If you remove items from this file, intellisense might break. ### C++ ### # Prerequisites @@ -151,11 +152,11 @@ gradle-app.setting # gradle/wrapper/gradle-wrapper.properties # # VS Code Specific Java Settings +# DO NOT REMOVE .classpath and .project .classpath .project .settings/ bin/ -imgui.ini - -# End of https://www.gitignore.io/api/c++,java,linux,macos,gradle,windows,visualstudiocode +# Simulation GUI and other tools window save file +*-window.json diff --git a/.templates/SubsystemTest.java b/.templates/SubsystemTest.java index 51f30d5..5755087 100644 --- a/.templates/SubsystemTest.java +++ b/.templates/SubsystemTest.java @@ -1,9 +1,6 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ +// 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 frc4388.robot.subsystems; diff --git a/.templates/UtilityTest.java b/.templates/UtilityTest.java index 035e580..c95cf29 100644 --- a/.templates/UtilityTest.java +++ b/.templates/UtilityTest.java @@ -1,9 +1,6 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ +// 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 frc4388.utility; diff --git a/.vscode/settings.json b/.vscode/settings.json index 5200b5c..4ed293b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "java.configuration.updateBuildConfiguration": "automatic", + "java.server.launchMode": "Standard", "files.exclude": { "**/.git": true, "**/.svn": true, @@ -10,6 +11,19 @@ "**/.classpath": true, "**/.project": true, "**/.settings": true, - "**/.factorypath": true - } + "**/.factorypath": true, + "**/*~": true + }, + "java.test.config": [ + { + "name": "WPIlibUnitTests", + "workingDirectory": "${workspaceFolder}/build/jni/release", + "vmargs": [ "-Djava.library.path=${workspaceFolder}/build/jni/release" ], + "env": { + "LD_LIBRARY_PATH": "${workspaceFolder}/build/jni/release" , + "DYLD_LIBRARY_PATH": "${workspaceFolder}/build/jni/release" + } + }, + ], + "java.test.defaultConfig": "WPIlibUnitTests" } diff --git a/.wpilib/wpilib_preferences.json b/.wpilib/wpilib_preferences.json index 0b623f1..dea47be 100644 --- a/.wpilib/wpilib_preferences.json +++ b/.wpilib/wpilib_preferences.json @@ -1,6 +1,6 @@ { "enableCppIntellisense": false, "currentLanguage": "java", - "projectYear": "2021", + "projectYear": "2022", "teamNumber": 4388 } \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index c714e13..0000000 --- a/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (c) 2009-2018 FIRST -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 the FIRST nor the - names of its 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 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. \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 3e57656..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# 2022 No Way Home -[![Java CI](https://github.com/Team4388/2022NoWayHome/actions/workflows/gradle.yml/badge.svg)](https://github.com/Team4388/2022NoWayHome/actions/workflows/gradle.yml) diff --git a/WPILib-License.md b/WPILib-License.md new file mode 100644 index 0000000..3d5a824 --- /dev/null +++ b/WPILib-License.md @@ -0,0 +1,24 @@ +Copyright (c) 2009-2021 FIRST and other WPILib contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of FIRST, WPILib, nor the names of other WPILib + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY FIRST AND OTHER WPILIB CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY NONINFRINGEMENT AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FIRST OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/build.gradle b/build.gradle index b0a450c..c1f07ee 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,8 @@ +import edu.wpi.first.gradlerio.deploy.roborio.RoboRIO + plugins { id "java" - id "edu.wpi.first.GradleRIO" version "2021.3.1" + id "edu.wpi.first.GradleRIO" version "2022.1.1" } sourceCompatibility = JavaVersion.VERSION_11 @@ -9,67 +11,69 @@ targetCompatibility = JavaVersion.VERSION_11 def ROBOT_MAIN_CLASS = "frc4388.robot.Main" // Define my targets (RoboRIO) and artifacts (deployable files) -// This is added by GradleRIO's backing project EmbeddedTools. +// This is added by GradleRIO's backing project DeployUtils. deploy { targets { - roboRIO("roborio") { + 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 = frc.getTeamNumber() - } - } - artifacts { - frcJavaArtifact('frcJava') { - targets << "roborio" - // Debug can be overridden by command line, for use with VSCode - debug = frc.getDebugOrDefault(false) - } - // Built in artifact to deploy arbitrary files to the roboRIO. - fileTreeArtifact('frcStaticFileDeploy') { - // The directory below is the local directory to deploy - files = fileTree(dir: 'src/main/deploy') - // Deploy to RoboRIO target, into /home/lvuser/deploy - targets << "roborio" - directory = '/home/lvuser/deploy' + team = project.frc.getTeamNumber() + debug = project.frc.getDebugOrDefault(false) + + artifacts { + // First part is artifact name, 2nd is artifact type + // getTargetTypeClass is a shortcut to get the class type using a string + + frcJava(getArtifactTypeClass('FRCJavaArtifact')) { + } + + // Static files artifact + frcStaticFileDeploy(getArtifactTypeClass('FileTreeArtifact')) { + files = project.fileTree('src/main/deploy') + directory = '/home/lvuser/deploy' + } + } } } } +def deployArtifact = deploy.targets.roborio.artifacts.frcJava + +// Set to true to use debug for JNI. +wpi.java.debugJni = false + // Set this to true to enable desktop support. def includeDesktopSupport = true // Defining my dependencies. In this case, WPILib (+ friends), and vendor libraries. // Also defines JUnit 4. dependencies { - implementation wpi.deps.wpilib() - nativeZip wpi.deps.wpilibJni(wpi.platforms.roborio) - nativeDesktopZip wpi.deps.wpilibJni(wpi.platforms.desktop) + 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) - implementation wpi.deps.vendor.java() - nativeZip wpi.deps.vendor.jni(wpi.platforms.roborio) - nativeDesktopZip wpi.deps.vendor.jni(wpi.platforms.desktop) + 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 'junit:junit:4.12' - testCompile "org.mockito:mockito-core:2.+" - - // Enable simulation gui support. Must check the box in vscode to enable support - // upon debugging - simulation wpi.deps.sim.gui(wpi.platforms.desktop, false) - simulation wpi.deps.sim.driverstation(wpi.platforms.desktop, false) - - // Websocket extensions require additional configuration. - // simulation wpi.deps.sim.ws_server(wpi.platforms.desktop, false) - // simulation wpi.deps.sim.ws_client(wpi.platforms.desktop, false) + testImplementation "org.mockito:mockito-core:2.+" } // Simulation configuration (e.g. environment variables). -sim { - // Sets the websocket client remote host. - // envVar "HALSIMWS_HOST", "10.0.0.2" -} +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 @@ -77,4 +81,10 @@ sim { jar { from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } manifest edu.wpi.first.gradlerio.GradleRIOPlugin.javaManifest(ROBOT_MAIN_CLASS) + duplicatesStrategy = DuplicatesStrategy.INCLUDE } + +// Configure jar and deploy tasks +deployArtifact.jarTask = jar +wpi.java.configureExecutableTasks(jar) +wpi.java.configureTestTasks(test) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index cc4fdc293d0e50b0ad9b65c16e7ddd1db2f6025b..7454180f2ae8848c63b8b4dea2cb829da983f2fa 100644 GIT binary patch delta 22213 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 delta 21233 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 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +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 -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # 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"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +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 - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +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" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -97,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || 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 @@ -105,79 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=`expr $i + 1` - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# 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. -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# 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 + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# 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/gradlew.bat b/gradlew.bat index 9618d8d..107acd3 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=. 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" @@ -37,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -51,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -61,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :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 %CMD_LINE_ARGS% +"%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 diff --git a/settings.gradle b/settings.gradle index 0bc697a..c363694 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,7 +4,7 @@ pluginManagement { repositories { mavenLocal() gradlePluginPortal() - String frcYear = '2021' + String frcYear = '2022' File frcHome if (OperatingSystem.current().isWindows()) { String publicFolder = System.getenv('PUBLIC') diff --git a/src/main/java/frc4388/robot/Constants.java b/src/main/java/frc4388/robot/Constants.java index 8258835..b6daa92 100644 --- a/src/main/java/frc4388/robot/Constants.java +++ b/src/main/java/frc4388/robot/Constants.java @@ -1,9 +1,6 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ +// 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 frc4388.robot; @@ -19,62 +16,51 @@ import frc4388.utility.LEDPatterns; * constants are needed, to reduce verbosity. */ public final class Constants { - public static final class ArcadeDriveConstants { - public static final int DRIVE_LEFT_FRONT_CAN_ID = 2; - public static final int DRIVE_RIGHT_FRONT_CAN_ID = 4; - public static final int DRIVE_LEFT_BACK_CAN_ID = 3; - public static final int DRIVE_RIGHT_BACK_CAN_ID = 5; - - public static final int DRIVE_PIGEON_ID = 6; + public static final class SwerveDriveConstants { + public static final double ROTATION_SPEED = 0.1; + public static final double WHEEL_SPEED = 0.1; + public static final double WIDTH = 22; + public static final double HEIGHT = 22; + public static final double JOYSTICK_TO_METERS_PER_SECOND = 5; + public static final double MAX_SPEED_FEET_PER_SEC = 16; + public static final double SPEED_FEET_PER_SECOND_AT_FULL_POWER = 20; + public static final int LEFT_FRONT_STEER_CAN_ID = 2; + public static final int LEFT_FRONT_WHEEL_CAN_ID = 3; + public static final int RIGHT_FRONT_STEER_CAN_ID = 4; + public static final int RIGHT_FRONT_WHEEL_CAN_ID = 5; + public static final int LEFT_BACK_STEER_CAN_ID = 6; + public static final int LEFT_BACK_WHEEL_CAN_ID = 7; + public static final int RIGHT_BACK_STEER_CAN_ID = 8; + public static final int RIGHT_BACK_WHEEL_CAN_ID = 9; + public static final int LEFT_FRONT_STEER_CAN_ENCODER_ID = 10; + public static final int RIGHT_FRONT_STEER_CAN_ENCODER_ID = 11; + public static final int LEFT_BACK_STEER_CAN_ENCODER_ID = 12; + public static final int RIGHT_BACK_STEER_CAN_ENCODER_ID = 13; + //ofsets are in degrees + public static final float LEFT_FRONT_ENCODER_OFFSET = 0; + public static final float RIGHT_FRONT_ENCODER_OFFSET = 0; + public static final float LEFT_BACK_ENCODER_OFFSET = 0; + public static final float RIGHT_BACK_ENCODER_OFFSET = 0; - public static final int SMARTDASHBOARD_UPDATE_FRAME = 2; - } + // swerve PID constants + public static final int SWERVE_SLOT_IDX = 0; + public static final int SWERVE_PID_LOOP_IDX = 1; + public static final int SWERVE_TIMEOUT_MS = 30; + public static final Gains SWERVE_GAINS = new Gains(1.0, 0.0, 0.0, 0.0, 0, 1.0); - public static final class SwerveDriveConstants { - public static final double ROTATION_SPEED = 0.1; - public static final double WHEEL_SPEED = 0.1; - public static final double WIDTH = 22; - public static final double HEIGHT = 22; - public static final double JOYSTICK_TO_METERS_PER_SECOND = 5; - public static final double MAX_SPEED_FEET_PER_SEC = 16; - public static final double SPEED_FEET_PER_SECOND_AT_FULL_POWER = 20; - public static final int LEFT_FRONT_STEER_CAN_ID = 2; - public static final int LEFT_FRONT_WHEEL_CAN_ID = 3; - public static final int RIGHT_FRONT_STEER_CAN_ID = 4; - public static final int RIGHT_FRONT_WHEEL_CAN_ID = 5; - public static final int LEFT_BACK_STEER_CAN_ID = 6; - public static final int LEFT_BACK_WHEEL_CAN_ID = 7; - public static final int RIGHT_BACK_STEER_CAN_ID = 8; - public static final int RIGHT_BACK_WHEEL_CAN_ID = 9; - public static final int LEFT_FRONT_STEER_CAN_ENCODER_ID = 10; - public static final int RIGHT_FRONT_STEER_CAN_ENCODER_ID = 11; - public static final int LEFT_BACK_STEER_CAN_ENCODER_ID = 12; - public static final int RIGHT_BACK_STEER_CAN_ENCODER_ID = 13; - //ofsets are in degrees - public static final float LEFT_FRONT_ENCODER_OFFSET = 0; - public static final float RIGHT_FRONT_ENCODER_OFFSET = 0; - public static final float LEFT_BACK_ENCODER_OFFSET = 0; - public static final float RIGHT_BACK_ENCODER_OFFSET = 0; + // swerve configuration + public static final double NEUTRAL_DEADBAND = 0.04; + public static final double OPEN_LOOP_RAMP_RATE = 0.2; + public static final int REMOTE_0 = 0; + } + public static final class LEDConstants { + public static final int LED_SPARK_ID = 0; - // swerve PID constants - public static final int SWERVE_SLOT_IDX = 0; - public static final int SWERVE_PID_LOOP_IDX = 1; - public static final int SWERVE_TIMEOUT_MS = 30; - public static final Gains SWERVE_GAINS = new Gains(1.0, 0.0, 0.0, 0.0, 0, 1.0); + public static final LEDPatterns DEFAULT_PATTERN = LEDPatterns.FOREST_WAVES; + } - // swerve configuration - public static final double NEUTRAL_DEADBAND = 0.04; - public static final double OPEN_LOOP_RAMP_RATE = 0.2; - public static final int REMOTE_0 = 0; - } - public static final class LEDConstants { - public static final int LED_SPARK_ID = 0; - - public static final LEDPatterns DEFAULT_PATTERN = LEDPatterns.FOREST_WAVES; - } - - public static final class OIConstants { - public static final int XBOX_DRIVER_ID = 0; - public static final int XBOX_OPERATOR_ID = 1; - } + public static final class OIConstants { + public static final int XBOX_DRIVER_ID = 0; + public static final int XBOX_OPERATOR_ID = 1; + } } diff --git a/src/main/java/frc4388/robot/Robot.java b/src/main/java/frc4388/robot/Robot.java index e145b38..b8962ad 100644 --- a/src/main/java/frc4388/robot/Robot.java +++ b/src/main/java/frc4388/robot/Robot.java @@ -75,12 +75,16 @@ public class Robot extends TimedRobot { public void autonomousInit() { m_autonomousCommand = m_robotContainer.getAutonomousCommand(); - /* - * String autoSelected = SmartDashboard.getString("Auto Selector", - * "Default"); switch(autoSelected) { case "My Auto": autonomousCommand - * = new MyAutoCommand(); break; case "Default Auto": default: - * autonomousCommand = new ExampleCommand(); break; } - */ + /*String autoSelected = SmartDashboard.getString("Auto Selector", "Default"); + switch (autoSelected) { + case "My Auto": + autonomousCommand = new MyAutoCommand(); + break; + case "Default Auto": + default: + autonomousCommand = new ExampleCommand(); + break; + }*/ // schedule the autonomous command (example) if (m_autonomousCommand != null) { diff --git a/src/main/java/frc4388/robot/RobotContainer.java b/src/main/java/frc4388/robot/RobotContainer.java index c697a7f..7b69652 100644 --- a/src/main/java/frc4388/robot/RobotContainer.java +++ b/src/main/java/frc4388/robot/RobotContainer.java @@ -1,9 +1,6 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ +// 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 frc4388.robot; @@ -13,7 +10,6 @@ import edu.wpi.first.wpilibj2.command.InstantCommand; import edu.wpi.first.wpilibj2.command.RunCommand; import edu.wpi.first.wpilibj2.command.button.JoystickButton; import frc4388.robot.Constants.*; -import frc4388.robot.subsystems.ArcadeDrive; import frc4388.robot.subsystems.LED; import frc4388.robot.subsystems.SwerveDrive; import frc4388.utility.LEDPatterns; @@ -28,105 +24,94 @@ import frc4388.utility.controller.XboxController; * commands, and button mappings) should be declared here. */ public class RobotContainer { - /* RobotMap */ - private final RobotMap m_robotMap = new RobotMap(); + /* RobotMap */ + private final RobotMap m_robotMap = new RobotMap(); - /* Subsystems */ - //private final ArcadeDrive m_robotArcadeDrive = new ArcadeDrive(m_robotMap.leftFrontMotor, m_robotMap.rightFrontMotor, - // m_robotMap.leftBackMotor, m_robotMap.rightBackMotor, m_robotMap.driveTrain, m_robotMap.gyroDrive); + /* Subsystems */ + private final SwerveDrive m_robotSwerveDrive = new SwerveDrive( + m_robotMap.leftFrontSteerMotor, m_robotMap.leftFrontWheelMotor, + m_robotMap.rightFrontSteerMotor, m_robotMap.rightFrontWheelMotor, + m_robotMap.leftBackSteerMotor, m_robotMap.leftBackWheelMotor, + m_robotMap.rightBackSteerMotor, m_robotMap.rightBackWheelMotor, + m_robotMap.leftFrontEncoder, + m_robotMap.rightFrontEncoder, + m_robotMap.leftBackEncoder, + m_robotMap.rightBackEncoder + ); - private final SwerveDrive m_robotSwerveDrive = new SwerveDrive( - m_robotMap.leftFrontSteerMotor, m_robotMap.leftFrontWheelMotor, - m_robotMap.rightFrontSteerMotor, m_robotMap.rightFrontWheelMotor, - m_robotMap.leftBackSteerMotor, m_robotMap.leftBackWheelMotor, - m_robotMap.rightBackSteerMotor, m_robotMap.rightBackWheelMotor, - m_robotMap.leftFrontEncoder, - m_robotMap.rightFrontEncoder, - m_robotMap.leftBackEncoder, - m_robotMap.rightBackEncoder - ); + private final LED m_robotLED = new LED(m_robotMap.LEDController); - private final LED m_robotLED = new LED(m_robotMap.LEDController); + /* Controllers */ + private final XboxController m_driverXbox = new XboxController(OIConstants.XBOX_DRIVER_ID); + private final XboxController m_operatorXbox = new XboxController(OIConstants.XBOX_OPERATOR_ID); - /* Controllers */ - private final XboxController m_driverXbox = new XboxController(OIConstants.XBOX_DRIVER_ID); - private final XboxController m_operatorXbox = new XboxController(OIConstants.XBOX_OPERATOR_ID); + /** + * The container for the robot. Contains subsystems, OI devices, and commands. + */ + public RobotContainer() { + configureButtonBindings(); - /** - * The container for the robot. Contains subsystems, OI devices, and commands. - */ - public RobotContainer() { - configureButtonBindings(); + /* Default Commands */ + // drives the swerve drive with a two-axis input from the driver controller + m_robotSwerveDrive.setDefaultCommand( + new RunCommand(() -> m_robotSwerveDrive.driveWithInput(getDriverController().getLeftXAxis(), + getDriverController().getLeftYAxis(), getDriverController().getRightXAxis(), false), m_robotSwerveDrive)); - /* Default Commands */ - // drives the arcade drive with a two-axis input from the driver controller - /*m_robotArcadeDrive.setDefaultCommand( - new RunCommand(() -> m_robotArcadeDrive.driveWithInput(getDriverController().getLeftYAxis(), - getDriverController().getRightXAxis()), m_robotArcadeDrive));*/ + // continually sends updates to the Blinkin LED controller to keep the lights on + m_robotLED.setDefaultCommand(new RunCommand(m_robotLED::updateLED, m_robotLED)); + } - // drives the swerve drive with a two-axis input from the driver controller - m_robotSwerveDrive.setDefaultCommand( - new RunCommand(() -> m_robotSwerveDrive.driveWithInput(getDriverController().getLeftXAxis(), - getDriverController().getLeftYAxis(), getDriverController().getRightXAxis(), false), m_robotSwerveDrive)); + /** + * Use this method to define your button->command mappings. Buttons can be + * created by instantiating a {@link GenericHID} or one of its subclasses + * ({@link edu.wpi.first.wpilibj.Joystick} or {@link XboxController}), and then + * passing it to a {@link edu.wpi.first.wpilibj2.command.button.JoystickButton}. + */ + private void configureButtonBindings() { + /* Driver Buttons */ - // continually sends updates to the Blinkin LED controller to keep the lights on - m_robotLED.setDefaultCommand(new RunCommand(() -> m_robotLED.updateLED(), m_robotLED)); - } + /* Operator Buttons */ + // activates "Lit Mode" + new JoystickButton(getOperatorJoystick(), XboxController.A_BUTTON) + .whenPressed(() -> m_robotLED.setPattern(LEDPatterns.LAVA_RAINBOW)) + .whenReleased(() -> m_robotLED.setPattern(LEDConstants.DEFAULT_PATTERN)); + } - /** - * Use this method to define your button->command mappings. Buttons can be - * created by instantiating a {@link GenericHID} or one of its subclasses - * ({@link edu.wpi.first.wpilibj.Joystick} or {@link XboxController}), and then - * passing it to a {@link edu.wpi.first.wpilibj2.command.button.JoystickButton}. - */ - private void configureButtonBindings() { - /* Driver Buttons */ - // test command to spin the robot while pressing A on the driver controller - //new JoystickButton(getDriverJoystick(), XboxController.A_BUTTON) - //.whileHeld(() -> m_robotArcadeDrive.driveWithInput(0, 1)); + /** + * Use this to pass the autonomous command to the main {@link Robot} class. + * + * @return the command to run in autonomous + */ + public Command getAutonomousCommand() { + // no auto + return new InstantCommand(); + } - /* Operator Buttons */ - // activates "Lit Mode" - new JoystickButton(getOperatorJoystick(), XboxController.A_BUTTON) - .whenPressed(() -> m_robotLED.setPattern(LEDPatterns.LAVA_RAINBOW)) - .whenReleased(() -> m_robotLED.setPattern(LEDConstants.DEFAULT_PATTERN)); - } + /** + * Add your docs here. + */ + public IHandController getDriverController() { + return m_driverXbox; + } - /** - * Use this to pass the autonomous command to the main {@link Robot} class. - * - * @return the command to run in autonomous - */ - public Command getAutonomousCommand() { - // no auto - return new InstantCommand(); - } + /** + * Add your docs here. + */ + public IHandController getOperatorController() { + return m_operatorXbox; + } - /** - * Add your docs here. - */ - public IHandController getDriverController() { - return m_driverXbox; - } + /** + * Add your docs here. + */ + public Joystick getOperatorJoystick() { + return m_operatorXbox.getJoyStick(); + } - /** - * Add your docs here. - */ - public IHandController getOperatorController() { - return m_operatorXbox; - } - - /** - * Add your docs here. - */ - public Joystick getOperatorJoystick() { - return m_operatorXbox.getJoyStick(); - } - - /** - * Add your docs here. - */ - public Joystick getDriverJoystick() { - return m_driverXbox.getJoyStick(); - } + /** + * Add your docs here. + */ + public Joystick getDriverJoystick() { + return m_driverXbox.getJoyStick(); + } } diff --git a/src/main/java/frc4388/robot/RobotMap.java b/src/main/java/frc4388/robot/RobotMap.java index d4e533f..843323c 100644 --- a/src/main/java/frc4388/robot/RobotMap.java +++ b/src/main/java/frc4388/robot/RobotMap.java @@ -1,26 +1,15 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ +// 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 frc4388.robot; -import com.ctre.phoenix.motorcontrol.InvertType; -import com.ctre.phoenix.motorcontrol.NeutralMode; -import com.ctre.phoenix.motorcontrol.RemoteSensorSource; import com.ctre.phoenix.motorcontrol.can.WPI_TalonFX; -import com.ctre.phoenix.sensors.PigeonIMU; -import com.ctre.phoenix.sensors.AbsoluteSensorRange; import com.ctre.phoenix.sensors.CANCoder; -import edu.wpi.first.wpilibj.Spark; -import edu.wpi.first.wpilibj.drive.DifferentialDrive; -import frc4388.robot.Constants.ArcadeDriveConstants; +import edu.wpi.first.wpilibj.motorcontrol.Spark; import frc4388.robot.Constants.LEDConstants; import frc4388.robot.Constants.SwerveDriveConstants; -import frc4388.utility.RobotGyro; /** * Defines and holds all I/O objects on the Roborio. This is useful for unit @@ -28,112 +17,79 @@ import frc4388.utility.RobotGyro; */ public class RobotMap { - public RobotMap() { - configureLEDMotorControllers(); - //configureArcadeDriveMotorControllers(); - configureSwerveMotorControllers(); - } + public RobotMap() { + configureLEDMotorControllers(); + configureSwerveMotorControllers(); + } - /* LED Subsystem */ - public final Spark LEDController = new Spark(LEDConstants.LED_SPARK_ID); + /* LED Subsystem */ + public final Spark LEDController = new Spark(LEDConstants.LED_SPARK_ID); - void configureLEDMotorControllers() { - - } + void configureLEDMotorControllers() { - /* ArcadeDrive Subsystem */ - //public final WPI_TalonFX leftFrontMotor = new WPI_TalonFX(ArcadeDriveConstants.DRIVE_LEFT_FRONT_CAN_ID); - //public final WPI_TalonFX rightFrontMotor = new WPI_TalonFX(ArcadeDriveConstants.DRIVE_RIGHT_FRONT_CAN_ID); - //public final WPI_TalonFX leftBackMotor = new WPI_TalonFX(ArcadeDriveConstants.DRIVE_LEFT_BACK_CAN_ID); - //public final WPI_TalonFX rightBackMotor = new WPI_TalonFX(ArcadeDriveConstants.DRIVE_RIGHT_BACK_CAN_ID); - //public final DifferentialDrive driveTrain = new DifferentialDrive(leftFrontMotor, rightFrontMotor); - //public final RobotGyro gyroDrive = new RobotGyro(new PigeonIMU(ArcadeDriveConstants.DRIVE_PIGEON_ID)); + } + + /* Swerve Subsystem */ + public final WPI_TalonFX leftFrontSteerMotor = new WPI_TalonFX(SwerveDriveConstants.LEFT_FRONT_STEER_CAN_ID); + public final WPI_TalonFX leftFrontWheelMotor = new WPI_TalonFX(SwerveDriveConstants.LEFT_FRONT_WHEEL_CAN_ID); + public final WPI_TalonFX rightFrontSteerMotor = new WPI_TalonFX(SwerveDriveConstants.RIGHT_FRONT_STEER_CAN_ID); + public final WPI_TalonFX rightFrontWheelMotor = new WPI_TalonFX(SwerveDriveConstants.RIGHT_FRONT_WHEEL_CAN_ID); + public final WPI_TalonFX leftBackSteerMotor = new WPI_TalonFX(SwerveDriveConstants.LEFT_BACK_STEER_CAN_ID); + public final WPI_TalonFX leftBackWheelMotor = new WPI_TalonFX(SwerveDriveConstants.LEFT_BACK_WHEEL_CAN_ID); + public final WPI_TalonFX rightBackSteerMotor = new WPI_TalonFX(SwerveDriveConstants.RIGHT_BACK_STEER_CAN_ID); + public final WPI_TalonFX rightBackWheelMotor = new WPI_TalonFX(SwerveDriveConstants.RIGHT_BACK_WHEEL_CAN_ID); + public final CANCoder leftFrontEncoder = new CANCoder(SwerveDriveConstants.LEFT_FRONT_STEER_CAN_ENCODER_ID); + public final CANCoder rightFrontEncoder = new CANCoder(SwerveDriveConstants.RIGHT_FRONT_STEER_CAN_ENCODER_ID); + public final CANCoder leftBackEncoder = new CANCoder(SwerveDriveConstants.LEFT_BACK_STEER_CAN_ENCODER_ID); + public final CANCoder rightBackEncoder = new CANCoder(SwerveDriveConstants.RIGHT_BACK_STEER_CAN_ENCODER_ID); + + void configureSwerveMotorControllers() { + leftFrontEncoder.configMagnetOffset(SwerveDriveConstants.LEFT_BACK_ENCODER_OFFSET); + rightFrontEncoder.configMagnetOffset(SwerveDriveConstants.RIGHT_FRONT_ENCODER_OFFSET); + leftBackEncoder.configMagnetOffset(SwerveDriveConstants.LEFT_BACK_ENCODER_OFFSET); + rightBackEncoder.configMagnetOffset(SwerveDriveConstants.RIGHT_BACK_ENCODER_OFFSET); - /*void configureArcadeDriveMotorControllers() { + leftFrontSteerMotor.configFactoryDefault(); + leftFrontWheelMotor.configFactoryDefault(); + rightFrontSteerMotor.configFactoryDefault(); + rightFrontWheelMotor.configFactoryDefault(); + leftBackSteerMotor.configFactoryDefault(); + leftBackWheelMotor.configFactoryDefault(); + rightBackSteerMotor.configFactoryDefault(); + rightBackWheelMotor.configFactoryDefault(); - // factory default values - leftFrontMotor.configFactoryDefault(); - rightFrontMotor.configFactoryDefault(); - leftBackMotor.configFactoryDefault(); - rightBackMotor.configFactoryDefault(); + leftFrontSteerMotor.configOpenloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + leftFrontWheelMotor.configOpenloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + rightFrontSteerMotor.configOpenloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + rightFrontWheelMotor.configOpenloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + leftBackSteerMotor.configOpenloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + leftBackWheelMotor.configOpenloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + rightBackSteerMotor.configOpenloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + rightBackWheelMotor.configOpenloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - // set back motors as followers - leftBackMotor.follow(leftFrontMotor); - rightBackMotor.follow(rightFrontMotor); + leftFrontWheelMotor.configClosedloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + leftFrontSteerMotor.configClosedloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + rightFrontSteerMotor.configClosedloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + rightFrontWheelMotor.configClosedloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + leftBackSteerMotor.configClosedloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + leftBackWheelMotor.configClosedloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + rightBackSteerMotor.configClosedloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + rightBackWheelMotor.configClosedloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - // set neutral mode - leftFrontMotor.setNeutralMode(NeutralMode.Brake); - rightFrontMotor.setNeutralMode(NeutralMode.Brake); - leftFrontMotor.setNeutralMode(NeutralMode.Brake); - rightFrontMotor.setNeutralMode(NeutralMode.Brake); + leftFrontWheelMotor.configNeutralDeadband(SwerveDriveConstants.NEUTRAL_DEADBAND, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + leftFrontSteerMotor.configNeutralDeadband(SwerveDriveConstants.NEUTRAL_DEADBAND, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + rightFrontSteerMotor.configNeutralDeadband(SwerveDriveConstants.NEUTRAL_DEADBAND, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + rightFrontWheelMotor.configNeutralDeadband(SwerveDriveConstants.NEUTRAL_DEADBAND, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + leftBackSteerMotor.configNeutralDeadband(SwerveDriveConstants.NEUTRAL_DEADBAND, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + leftBackWheelMotor.configNeutralDeadband(SwerveDriveConstants.NEUTRAL_DEADBAND, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + rightBackSteerMotor.configNeutralDeadband(SwerveDriveConstants.NEUTRAL_DEADBAND, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + rightBackWheelMotor.configNeutralDeadband(SwerveDriveConstants.NEUTRAL_DEADBAND, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - // flip input so forward becomes back, etc - leftFrontMotor.setInverted(false); - rightFrontMotor.setInverted(false); - leftBackMotor.setInverted(InvertType.FollowMaster); - rightBackMotor.setInverted(InvertType.FollowMaster); - }*/ - /* Swerve Subsystem */ - public final WPI_TalonFX leftFrontSteerMotor = new WPI_TalonFX(SwerveDriveConstants.LEFT_FRONT_STEER_CAN_ID); - public final WPI_TalonFX leftFrontWheelMotor = new WPI_TalonFX(SwerveDriveConstants.LEFT_FRONT_WHEEL_CAN_ID); - public final WPI_TalonFX rightFrontSteerMotor = new WPI_TalonFX(SwerveDriveConstants.RIGHT_FRONT_STEER_CAN_ID); - public final WPI_TalonFX rightFrontWheelMotor = new WPI_TalonFX(SwerveDriveConstants.RIGHT_FRONT_WHEEL_CAN_ID); - public final WPI_TalonFX leftBackSteerMotor = new WPI_TalonFX(SwerveDriveConstants.LEFT_BACK_STEER_CAN_ID); - public final WPI_TalonFX leftBackWheelMotor = new WPI_TalonFX(SwerveDriveConstants.LEFT_BACK_WHEEL_CAN_ID); - public final WPI_TalonFX rightBackSteerMotor = new WPI_TalonFX(SwerveDriveConstants.RIGHT_BACK_STEER_CAN_ID); - public final WPI_TalonFX rightBackWheelMotor = new WPI_TalonFX(SwerveDriveConstants.RIGHT_BACK_WHEEL_CAN_ID); - public final CANCoder leftFrontEncoder = new CANCoder(SwerveDriveConstants.LEFT_FRONT_STEER_CAN_ENCODER_ID); - public final CANCoder rightFrontEncoder = new CANCoder(SwerveDriveConstants.RIGHT_FRONT_STEER_CAN_ENCODER_ID); - public final CANCoder leftBackEncoder = new CANCoder(SwerveDriveConstants.LEFT_BACK_STEER_CAN_ENCODER_ID); - public final CANCoder rightBackEncoder = new CANCoder(SwerveDriveConstants.RIGHT_BACK_STEER_CAN_ENCODER_ID); - - void configureSwerveMotorControllers() { - leftFrontEncoder.configMagnetOffset(SwerveDriveConstants.LEFT_BACK_ENCODER_OFFSET); - rightFrontEncoder.configMagnetOffset(SwerveDriveConstants.RIGHT_FRONT_ENCODER_OFFSET); - leftBackEncoder.configMagnetOffset(SwerveDriveConstants.LEFT_BACK_ENCODER_OFFSET); - rightBackEncoder.configMagnetOffset(SwerveDriveConstants.RIGHT_BACK_ENCODER_OFFSET); - - leftFrontSteerMotor.configFactoryDefault(); - leftFrontWheelMotor.configFactoryDefault(); - rightFrontSteerMotor.configFactoryDefault(); - rightFrontWheelMotor.configFactoryDefault(); - leftBackSteerMotor.configFactoryDefault(); - leftBackWheelMotor.configFactoryDefault(); - rightBackSteerMotor.configFactoryDefault(); - rightBackWheelMotor.configFactoryDefault(); - - leftFrontSteerMotor.configOpenloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - leftFrontWheelMotor.configOpenloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - rightFrontSteerMotor.configOpenloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - rightFrontWheelMotor.configOpenloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - leftBackSteerMotor.configOpenloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - leftBackWheelMotor.configOpenloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - rightBackSteerMotor.configOpenloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - rightBackWheelMotor.configOpenloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - - leftFrontWheelMotor.configClosedloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - leftFrontSteerMotor.configClosedloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - rightFrontSteerMotor.configClosedloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - rightFrontWheelMotor.configClosedloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - leftBackSteerMotor.configClosedloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - leftBackWheelMotor.configClosedloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - rightBackSteerMotor.configClosedloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - rightBackWheelMotor.configClosedloopRamp(SwerveDriveConstants.OPEN_LOOP_RAMP_RATE, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - - leftFrontWheelMotor.configNeutralDeadband(SwerveDriveConstants.NEUTRAL_DEADBAND, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - leftFrontSteerMotor.configNeutralDeadband(SwerveDriveConstants.NEUTRAL_DEADBAND, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - rightFrontSteerMotor.configNeutralDeadband(SwerveDriveConstants.NEUTRAL_DEADBAND, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - rightFrontWheelMotor.configNeutralDeadband(SwerveDriveConstants.NEUTRAL_DEADBAND, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - leftBackSteerMotor.configNeutralDeadband(SwerveDriveConstants.NEUTRAL_DEADBAND, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - leftBackWheelMotor.configNeutralDeadband(SwerveDriveConstants.NEUTRAL_DEADBAND, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - rightBackSteerMotor.configNeutralDeadband(SwerveDriveConstants.NEUTRAL_DEADBAND, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - rightBackWheelMotor.configNeutralDeadband(SwerveDriveConstants.NEUTRAL_DEADBAND, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - - // config cancoder as remote encoder for swerve steer motors - //leftFrontSteerMotor.configRemoteFeedbackFilter(leftFrontEncoder.getDeviceID(), RemoteSensorSource.CANCoder, SwerveDriveConstants.REMOTE_0, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - //leftBackSteerMotor.configRemoteFeedbackFilter(leftBackEncoder.getDeviceID(), RemoteSensorSource.CANCoder, SwerveDriveConstants.REMOTE_0, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - //rightFrontSteerMotor.configRemoteFeedbackFilter(rightFrontEncoder.getDeviceID(), RemoteSensorSource.CANCoder, SwerveDriveConstants.REMOTE_0, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - //rightBackSteerMotor.configRemoteFeedbackFilter(rightBackEncoder.getDeviceID(), RemoteSensorSource.CANCoder, SwerveDriveConstants.REMOTE_0, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - } + // config cancoder as remote encoder for swerve steer motors + //leftFrontSteerMotor.configRemoteFeedbackFilter(leftFrontEncoder.getDeviceID(), RemoteSensorSource.CANCoder, SwerveDriveConstants.REMOTE_0, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + //leftBackSteerMotor.configRemoteFeedbackFilter(leftBackEncoder.getDeviceID(), RemoteSensorSource.CANCoder, SwerveDriveConstants.REMOTE_0, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + //rightFrontSteerMotor.configRemoteFeedbackFilter(rightFrontEncoder.getDeviceID(), RemoteSensorSource.CANCoder, SwerveDriveConstants.REMOTE_0, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + //rightBackSteerMotor.configRemoteFeedbackFilter(rightBackEncoder.getDeviceID(), RemoteSensorSource.CANCoder, SwerveDriveConstants.REMOTE_0, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + } } diff --git a/src/main/java/frc4388/robot/subsystems/ArcadeDrive.java b/src/main/java/frc4388/robot/subsystems/ArcadeDrive.java deleted file mode 100644 index f06a547..0000000 --- a/src/main/java/frc4388/robot/subsystems/ArcadeDrive.java +++ /dev/null @@ -1,85 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018 FIRST. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ - -package frc4388.robot.subsystems; - -import com.ctre.phoenix.motorcontrol.can.WPI_TalonFX; - -import edu.wpi.first.wpilibj.drive.DifferentialDrive; -import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; -import edu.wpi.first.wpilibj2.command.SubsystemBase; - -import frc4388.robot.Constants.ArcadeDriveConstants; -import frc4388.utility.RobotGyro; -import frc4388.utility.RobotTime; - -/** - * Add your docs here. - */ -public class ArcadeDrive extends SubsystemBase { - // Put methods for controlling this subsystem - // here. Call these from Commands. - - private RobotTime m_robotTime = RobotTime.getInstance(); - - private WPI_TalonFX m_leftFrontMotor; - private WPI_TalonFX m_rightFrontMotor; - private WPI_TalonFX m_leftBackMotor; - private WPI_TalonFX m_rightBackMotor; - private DifferentialDrive m_driveTrain; - private RobotGyro m_gyro; - - /** - * Add your docs here. - */ - public ArcadeDrive(WPI_TalonFX leftFrontMotor, WPI_TalonFX rightFrontMotor, WPI_TalonFX leftBackMotor, - WPI_TalonFX rightBackMotor, DifferentialDrive driveTrain, RobotGyro gyro) { - - m_leftFrontMotor = leftFrontMotor; - m_rightFrontMotor = rightFrontMotor; - m_leftBackMotor = leftBackMotor; - m_rightBackMotor = rightBackMotor; - m_driveTrain = driveTrain; - m_gyro = gyro; - } - - @Override - public void periodic() { - m_gyro.updatePigeonDeltas(); - - if (m_robotTime.m_frameNumber % ArcadeDriveConstants.SMARTDASHBOARD_UPDATE_FRAME == 0) { - updateSmartDashboard(); - } - } - - /** - * Add your docs here. - */ - public void driveWithInput(double move, double steer) { - m_driveTrain.arcadeDrive(move, steer); - } - - /** - * Add your docs here. - */ - public void tankDriveWithInput(double leftMove, double rightMove) { - m_leftFrontMotor.set(leftMove); - m_rightFrontMotor.set(rightMove); - } - - /** - * Add your docs here. - */ - private void updateSmartDashboard() { - - // Examples of the functionality of RobotGyro - SmartDashboard.putBoolean("Is Gyro a Pigeon?", m_gyro.m_isGyroAPigeon); - SmartDashboard.putNumber("Turn Rate", m_gyro.getRate()); - SmartDashboard.putNumber("Gyro Pitch", m_gyro.getPitch()); - SmartDashboard.putData(m_gyro); - } -} diff --git a/src/main/java/frc4388/robot/subsystems/LED.java b/src/main/java/frc4388/robot/subsystems/LED.java index 57c7b58..0d4af80 100644 --- a/src/main/java/frc4388/robot/subsystems/LED.java +++ b/src/main/java/frc4388/robot/subsystems/LED.java @@ -7,7 +7,7 @@ package frc4388.robot.subsystems; -import edu.wpi.first.wpilibj.Spark; +import edu.wpi.first.wpilibj.motorcontrol.Spark; import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; import edu.wpi.first.wpilibj2.command.SubsystemBase; diff --git a/src/main/java/frc4388/robot/subsystems/SwerveDrive.java b/src/main/java/frc4388/robot/subsystems/SwerveDrive.java index 6ba30b8..0ac4044 100644 --- a/src/main/java/frc4388/robot/subsystems/SwerveDrive.java +++ b/src/main/java/frc4388/robot/subsystems/SwerveDrive.java @@ -1,194 +1,177 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018 FIRST. All Rights Reserved. */ +/* Copyright (c) 2018 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ +/* the project. */ /*----------------------------------------------------------------------------*/ package frc4388.robot.subsystems; -import com.ctre.phoenix.motorcontrol.TalonFXControlMode; import com.ctre.phoenix.motorcontrol.can.WPI_TalonFX; import com.ctre.phoenix.sensors.CANCoder; -import edu.wpi.first.wpilibj.geometry.Rotation2d; -import edu.wpi.first.wpilibj.geometry.Translation2d; -import edu.wpi.first.wpilibj.kinematics.ChassisSpeeds; -import edu.wpi.first.wpilibj.kinematics.SwerveDriveKinematics; -import edu.wpi.first.wpilibj.kinematics.SwerveModuleState; -import edu.wpi.first.wpilibj.util.Units; +import edu.wpi.first.math.geometry.Rotation2d; +import edu.wpi.first.math.geometry.Translation2d; +import edu.wpi.first.math.kinematics.ChassisSpeeds; +import edu.wpi.first.math.kinematics.SwerveDriveKinematics; +import edu.wpi.first.math.kinematics.SwerveModuleState; +import edu.wpi.first.math.util.Units; +import edu.wpi.first.wpilibj.interfaces.Gyro; import edu.wpi.first.wpilibj2.command.SubsystemBase; import frc4388.robot.Constants.SwerveDriveConstants; import frc4388.utility.Gains; -import frc4388.utility.RobotGyro; -public class SwerveDrive extends SubsystemBase -{ - SwerveDriveKinematics m_kinematics; - private WPI_TalonFX m_leftFrontSteerMotor; - private WPI_TalonFX m_leftFrontWheelMotor; - private WPI_TalonFX m_rightFrontSteerMotor; - private WPI_TalonFX m_rightFrontWheelMotor; - private WPI_TalonFX m_leftBackSteerMotor; - private WPI_TalonFX m_leftBackWheelMotor; - private WPI_TalonFX m_rightBackSteerMotor; - private WPI_TalonFX m_rightBackWheelMotor; - private CANCoder m_leftFrontEncoder; - private CANCoder m_rightFrontEncoder; - private CANCoder m_leftBackEncoder; - private CANCoder m_rightBackEncoder; - double halfWidth = SwerveDriveConstants.WIDTH / 2.d; - double halfHeight = SwerveDriveConstants.HEIGHT / 2.d; - public static Gains m_swerveGains = SwerveDriveConstants.SWERVE_GAINS; +public class SwerveDrive extends SubsystemBase { + SwerveDriveKinematics m_kinematics; + private WPI_TalonFX m_leftFrontSteerMotor; + private WPI_TalonFX m_leftFrontWheelMotor; + private WPI_TalonFX m_rightFrontSteerMotor; + private WPI_TalonFX m_rightFrontWheelMotor; + private WPI_TalonFX m_leftBackSteerMotor; + private WPI_TalonFX m_leftBackWheelMotor; + private WPI_TalonFX m_rightBackSteerMotor; + private WPI_TalonFX m_rightBackWheelMotor; + private CANCoder m_leftFrontEncoder; + private CANCoder m_rightFrontEncoder; + private CANCoder m_leftBackEncoder; + private CANCoder m_rightBackEncoder; + double halfWidth = SwerveDriveConstants.WIDTH / 2.d; + double halfHeight = SwerveDriveConstants.HEIGHT / 2.d; + public static Gains m_swerveGains = SwerveDriveConstants.SWERVE_GAINS; + Translation2d m_frontLeftLocation = new Translation2d(Units.inchesToMeters(halfHeight), Units.inchesToMeters(halfWidth)); + Translation2d m_frontRightLocation = new Translation2d(Units.inchesToMeters(halfHeight), Units.inchesToMeters(-halfWidth)); + Translation2d m_backLeftLocation = new Translation2d(Units.inchesToMeters(-halfHeight), Units.inchesToMeters(halfWidth)); + Translation2d m_backRightLocation = new Translation2d(Units.inchesToMeters(-halfHeight), Units.inchesToMeters(-halfWidth)); + // setSwerveGains(); - Translation2d m_frontLeftLocation = - new Translation2d( - Units.inchesToMeters(halfHeight), - Units.inchesToMeters(halfWidth)); - Translation2d m_frontRightLocation = - new Translation2d( - Units.inchesToMeters(halfHeight), - Units.inchesToMeters(-halfWidth)); - Translation2d m_backLeftLocation = - new Translation2d( - Units.inchesToMeters(-halfHeight), - Units.inchesToMeters(halfWidth)); - Translation2d m_backRightLocation = - new Translation2d( - Units.inchesToMeters(-halfHeight), - Units.inchesToMeters(-halfWidth)); - //setSwerveGains(); - - private SwerveDriveKinematics kinematics = new SwerveDriveKinematics(m_frontLeftLocation, m_frontRightLocation, m_backLeftLocation, m_backRightLocation); - public SwerveModule[] modules; - public RobotGyro gyro; //TODO Add Gyro Lol + private SwerveDriveKinematics kinematics = new SwerveDriveKinematics(m_frontLeftLocation, m_frontRightLocation, m_backLeftLocation, m_backRightLocation); + public SwerveModule[] modules; + public Gyro gyro; // TODO Add Gyro Lol + public SwerveDrive(WPI_TalonFX leftFrontSteerMotor, WPI_TalonFX leftFrontWheelMotor, + WPI_TalonFX rightFrontSteerMotor, WPI_TalonFX rightFrontWheelMotor, + WPI_TalonFX leftBackSteerMotor, WPI_TalonFX leftBackWheelMotor, + WPI_TalonFX rightBackSteerMotor, WPI_TalonFX rightBackWheelMotor, + CANCoder leftFrontEncoder, CANCoder rightFrontEncoder, + CANCoder leftBackEncoder, CANCoder rightBackEncoder) { + m_leftFrontSteerMotor = leftFrontSteerMotor; + m_leftFrontWheelMotor = leftFrontWheelMotor; + m_rightFrontSteerMotor = rightFrontSteerMotor; + m_rightFrontWheelMotor = rightFrontWheelMotor; + m_leftBackSteerMotor = leftBackSteerMotor; + m_leftBackWheelMotor = leftBackWheelMotor; + m_rightBackSteerMotor = rightBackSteerMotor; + m_rightBackWheelMotor = rightBackWheelMotor; + m_leftFrontEncoder = leftFrontEncoder; + m_rightFrontEncoder = rightFrontEncoder; + m_leftBackEncoder = leftBackEncoder; + m_rightBackEncoder = rightBackEncoder; - public SwerveDrive(WPI_TalonFX leftFrontSteerMotor,WPI_TalonFX leftFrontWheelMotor,WPI_TalonFX rightFrontSteerMotor,WPI_TalonFX rightFrontWheelMotor, - WPI_TalonFX leftBackSteerMotor,WPI_TalonFX leftBackWheelMotor,WPI_TalonFX rightBackSteerMotor,WPI_TalonFX rightBackWheelMotor, CANCoder leftFrontEncoder, - CANCoder rightFrontEncoder, - CANCoder leftBackEncoder, - CANCoder rightBackEncoder) - { - m_leftFrontSteerMotor = leftFrontSteerMotor; - m_leftFrontWheelMotor = leftFrontWheelMotor; - m_rightFrontSteerMotor = rightFrontSteerMotor; - m_rightFrontWheelMotor = rightFrontWheelMotor; - m_leftBackSteerMotor = leftBackSteerMotor; - m_leftBackWheelMotor = leftBackWheelMotor; - m_rightBackSteerMotor = rightBackSteerMotor; - m_rightBackWheelMotor = rightBackWheelMotor; - m_leftFrontEncoder = leftFrontEncoder; - m_rightFrontEncoder = rightFrontEncoder; - m_leftBackEncoder = leftBackEncoder; - m_rightBackEncoder = rightBackEncoder; + modules = new SwerveModule[] { + new SwerveModule(m_leftFrontWheelMotor, m_leftFrontSteerMotor, m_leftFrontEncoder), // Front Left + new SwerveModule(m_rightFrontWheelMotor, m_rightFrontSteerMotor, m_rightFrontEncoder), // Front Right + new SwerveModule(m_leftBackWheelMotor, m_leftBackSteerMotor, m_leftBackEncoder), // Back Left + new SwerveModule(m_rightBackWheelMotor, m_rightBackSteerMotor, m_rightBackEncoder) // Back Right + }; + // gyro.reset(); + } - modules = new SwerveModule[] { - new SwerveModule(m_leftFrontWheelMotor, m_leftFrontSteerMotor, m_leftFrontEncoder), // Front Left - new SwerveModule(m_rightFrontWheelMotor, m_rightFrontSteerMotor, m_rightFrontEncoder), // Front Right - new SwerveModule(m_leftBackWheelMotor, m_leftBackSteerMotor, m_leftBackEncoder), // Back Left - new SwerveModule(m_rightBackWheelMotor, m_rightBackSteerMotor, m_rightBackEncoder) // Back Right - }; - //gyro.reset(); - } -//https://github.com/ZachOrr/MK3-Swerve-Example - /** + // https://github.com/ZachOrr/MK3-Swerve-Example + /** * Method to drive the robot using joystick info. * - * @param xSpeed Speed of the robot in the x direction (forward). - * @param ySpeed Speed of the robot in the y direction (sideways). - * @param rot Angular rate of the robot. - * @param fieldRelative Whether the provided x and y speeds are relative to the field. + * @param xSpeed Speed of the robot in the x direction (forward). + * @param ySpeed Speed of the robot in the y direction (sideways). + * @param rot Angular rate of the robot. + * @param fieldRelative Whether the provided x and y speeds are relative to the + * field. */ - public void driveWithInput(double xSpeed, double ySpeed, double rot, boolean fieldRelative) - { - /*var speeds = new ChassisSpeeds(strafeX, strafeY, rotate * SwerveDriveConstants.ROTATION_SPEED //in rad/s ); - driveFromSpeeds(speeds);*/ - double xSpeedMetersPerSecond = xSpeed * SwerveDriveConstants.JOYSTICK_TO_METERS_PER_SECOND; - double ySpeedMetersPerSecond = ySpeed * SwerveDriveConstants.JOYSTICK_TO_METERS_PER_SECOND; - SwerveModuleState[] states = - kinematics.toSwerveModuleStates( - fieldRelative - ? ChassisSpeeds.fromFieldRelativeSpeeds(xSpeedMetersPerSecond, ySpeedMetersPerSecond, rot, gyro.getRotation2d()) - : new ChassisSpeeds(xSpeedMetersPerSecond, ySpeedMetersPerSecond, rot)); - SwerveDriveKinematics.normalizeWheelSpeeds(states, Units.feetToMeters(SwerveDriveConstants.MAX_SPEED_FEET_PER_SEC)); - for (int i = 0; i < states.length; i++) { - SwerveModule module = modules[i]; - SwerveModuleState state = states[i]; - module.setDesiredState(state); + public void driveWithInput(double xSpeed, double ySpeed, double rot, boolean fieldRelative) { + + // var speeds = new ChassisSpeeds(strafeX, strafeY, rotate * SwerveDriveConstants.ROTATION_SPEED //in rad/s ); + // driveFromSpeeds(speeds); + + double xSpeedMetersPerSecond = xSpeed * SwerveDriveConstants.JOYSTICK_TO_METERS_PER_SECOND; + double ySpeedMetersPerSecond = ySpeed * SwerveDriveConstants.JOYSTICK_TO_METERS_PER_SECOND; + SwerveModuleState[] states = kinematics.toSwerveModuleStates( + fieldRelative ? ChassisSpeeds.fromFieldRelativeSpeeds(xSpeedMetersPerSecond, ySpeedMetersPerSecond, rot, gyro.getRotation2d()) + : new ChassisSpeeds(xSpeedMetersPerSecond, ySpeedMetersPerSecond, rot)); + SwerveDriveKinematics.desaturateWheelSpeeds(states, Units.feetToMeters(SwerveDriveConstants.MAX_SPEED_FEET_PER_SEC)); + for (int i = 0; i < states.length; i++) { + SwerveModule module = modules[i]; + SwerveModuleState state = states[i]; + module.setDesiredState(state); } - } - //Converts a ChassisSpeed to SwerveModuleStates (targets) - public void driveFromSpeeds(ChassisSpeeds speeds) - { - //https://docs.wpilib.org/en/stable/docs/software/kinematics-and-odometry/swerve-drive-kinematics.html - // Convert to module states - SwerveModuleState[] moduleStates = m_kinematics.toSwerveModuleStates(speeds); + } - // Front left module state - SwerveModuleState leftFront = SwerveModuleState.optimize(moduleStates[0], Rotation2d.fromDegrees(m_leftFrontEncoder.getPosition())); - // Front right module state - SwerveModuleState rightFront = SwerveModuleState.optimize(moduleStates[1], Rotation2d.fromDegrees(m_rightFrontEncoder.getPosition())); - // Back left module state - SwerveModuleState leftBack = SwerveModuleState.optimize(moduleStates[2], Rotation2d.fromDegrees(m_leftBackEncoder.getPosition())); - // Back right module state - SwerveModuleState rightBack = SwerveModuleState.optimize(moduleStates[3], Rotation2d.fromDegrees(m_rightBackEncoder.getPosition())); - - //Set the motors - setSwerveMotors(leftFront, leftBack, rightFront, rightBack); - } + // Converts a ChassisSpeed to SwerveModuleStates (targets) + public void driveFromSpeeds(ChassisSpeeds speeds) { + // https://docs.wpilib.org/en/stable/docs/software/kinematics-and-odometry/swerve-drive-kinematics.html + // Convert to module states + SwerveModuleState[] moduleStates = m_kinematics.toSwerveModuleStates(speeds); - //Sets steering motors to PID values - public void setSwerveMotors(SwerveModuleState leftFront, SwerveModuleState leftBack, SwerveModuleState rightFront, SwerveModuleState rightBack) - { - /*//Set the Wheel motor speeds - m_leftFrontWheelMotor.set(m_leftFrontSteerMotor.get() + leftFront.speedMetersPerSecond * SwerveDriveConstants.WHEEL_SPEED); - m_rightFrontWheelMotor.set(m_rightFrontSteerMotor.get() + rightFront.speedMetersPerSecond * SwerveDriveConstants.WHEEL_SPEED); - m_leftBackWheelMotor.set(m_leftBackSteerMotor.get() + leftBack.speedMetersPerSecond * SwerveDriveConstants.WHEEL_SPEED); - m_rightBackWheelMotor.set(m_rightBackSteerMotor.get() + rightBack.speedMetersPerSecond * SwerveDriveConstants.WHEEL_SPEED); + // Front left module state + SwerveModuleState leftFront = SwerveModuleState.optimize(moduleStates[0], Rotation2d.fromDegrees(m_leftFrontEncoder.getPosition())); + // Front right module state + SwerveModuleState rightFront = SwerveModuleState.optimize(moduleStates[1], Rotation2d.fromDegrees(m_rightFrontEncoder.getPosition())); + // Back left module state + SwerveModuleState leftBack = SwerveModuleState.optimize(moduleStates[2], Rotation2d.fromDegrees(m_leftBackEncoder.getPosition())); + // Back right module state + SwerveModuleState rightBack = SwerveModuleState.optimize(moduleStates[3], Rotation2d.fromDegrees(m_rightBackEncoder.getPosition())); - //PID - m_leftFrontSteerMotor.set(TalonFXControlMode.Position, leftFront.angle.getDegrees() * 12000); - m_rightFrontSteerMotor.set(TalonFXControlMode.Position, rightFront.angle.getDegrees() * 12000); - m_leftBackSteerMotor.set(TalonFXControlMode.Position, leftBack.angle.getDegrees() * 12000); - m_rightBackSteerMotor.set(TalonFXControlMode.Position, rightBack.angle.getDegrees()); + // Set the motors + setSwerveMotors(leftFront, leftBack, rightFront, rightBack); + } + //Sets steering motors to PID values + public void setSwerveMotors(SwerveModuleState leftFront, SwerveModuleState leftBack, SwerveModuleState rightFront, SwerveModuleState rightBack) + {/* + //Set the Wheel motor speeds + m_leftFrontWheelMotor.set(m_leftFrontSteerMotor.get() + leftFront.speedMetersPerSecond * SwerveDriveConstants.WHEEL_SPEED); + m_rightFrontWheelMotor.set(m_rightFrontSteerMotor.get() + rightFront.speedMetersPerSecond * SwerveDriveConstants.WHEEL_SPEED); + m_leftBackWheelMotor.set(m_leftBackSteerMotor.get() + leftBack.speedMetersPerSecond * SwerveDriveConstants.WHEEL_SPEED); + m_rightBackWheelMotor.set(m_rightBackSteerMotor.get() + rightBack.speedMetersPerSecond * SwerveDriveConstants.WHEEL_SPEED); - System.out.println("Target: " + leftFront.angle.getDegrees());*/ - } + //PID + m_leftFrontSteerMotor.set(TalonFXControlMode.Position, leftFront.angle.getDegrees() * 12000); + m_rightFrontSteerMotor.set(TalonFXControlMode.Position, rightFront.angle.getDegrees() * 12000); + m_leftBackSteerMotor.set(TalonFXControlMode.Position, leftBack.angle.getDegrees() * 12000); + m_rightBackSteerMotor.set(TalonFXControlMode.Position, rightBack.angle.getDegrees()); + + System.out.println("Target: " + leftFront.angle.getDegrees()); + */} + + /*public void setSwerveGains(){ + m_leftFrontSteerMotor.selectProfileSlot(SwerveDriveConstants.SWERVE_SLOT_IDX, SwerveDriveConstants.SWERVE_PID_LOOP_IDX); + m_leftFrontSteerMotor.config_kF(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kF, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + m_leftFrontSteerMotor.config_kP(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kP, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + m_leftFrontSteerMotor.config_kI(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kI, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + m_leftFrontSteerMotor.config_kD(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kD, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + + m_rightFrontSteerMotor.selectProfileSlot(SwerveDriveConstants.SWERVE_SLOT_IDX, SwerveDriveConstants.SWERVE_PID_LOOP_IDX); + m_rightFrontSteerMotor.config_kF(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kF, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + m_rightFrontSteerMotor.config_kP(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kP, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + m_rightFrontSteerMotor.config_kI(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kI, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + m_rightFrontSteerMotor.config_kD(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kD, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + + m_leftBackSteerMotor.selectProfileSlot(SwerveDriveConstants.SWERVE_SLOT_IDX, SwerveDriveConstants.SWERVE_PID_LOOP_IDX); + m_leftBackSteerMotor.config_kF(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kF, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + m_leftBackSteerMotor.config_kP(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kP, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + m_leftBackSteerMotor.config_kI(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kI, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + m_leftBackSteerMotor.config_kD(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kD, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + + m_rightBackSteerMotor.selectProfileSlot(SwerveDriveConstants.SWERVE_SLOT_IDX, SwerveDriveConstants.SWERVE_PID_LOOP_IDX); + m_rightBackSteerMotor.config_kF(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kF, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + m_rightBackSteerMotor.config_kP(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kP, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + m_rightBackSteerMotor.config_kI(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kI, SwerveDriveConstants.SWERVE_TIMEOUT_MS); + m_rightBackSteerMotor.config_kD(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kD, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - /*public void setSwerveGains(){ - m_leftFrontSteerMotor.selectProfileSlot(SwerveDriveConstants.SWERVE_SLOT_IDX, SwerveDriveConstants.SWERVE_PID_LOOP_IDX); - m_leftFrontSteerMotor.config_kF(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kF, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - m_leftFrontSteerMotor.config_kP(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kP, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - m_leftFrontSteerMotor.config_kI(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kI, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - m_leftFrontSteerMotor.config_kD(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kD, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - - m_rightFrontSteerMotor.selectProfileSlot(SwerveDriveConstants.SWERVE_SLOT_IDX, SwerveDriveConstants.SWERVE_PID_LOOP_IDX); - m_rightFrontSteerMotor.config_kF(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kF, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - m_rightFrontSteerMotor.config_kP(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kP, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - m_rightFrontSteerMotor.config_kI(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kI, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - m_rightFrontSteerMotor.config_kD(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kD, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - - m_leftBackSteerMotor.selectProfileSlot(SwerveDriveConstants.SWERVE_SLOT_IDX, SwerveDriveConstants.SWERVE_PID_LOOP_IDX); - m_leftBackSteerMotor.config_kF(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kF, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - m_leftBackSteerMotor.config_kP(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kP, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - m_leftBackSteerMotor.config_kI(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kI, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - m_leftBackSteerMotor.config_kD(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kD, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - - m_rightBackSteerMotor.selectProfileSlot(SwerveDriveConstants.SWERVE_SLOT_IDX, SwerveDriveConstants.SWERVE_PID_LOOP_IDX); - m_rightBackSteerMotor.config_kF(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kF, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - m_rightBackSteerMotor.config_kP(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kP, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - m_rightBackSteerMotor.config_kI(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kI, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - m_rightBackSteerMotor.config_kD(SwerveDriveConstants.SWERVE_SLOT_IDX, m_swerveGains.m_kD, SwerveDriveConstants.SWERVE_TIMEOUT_MS); - - }*/ + }*/ - // public void driveFieldRelative(double awayFromStation, double towardLeftBoundary, double rotate) - // { - // var speeds = ChassisSpeeds.fromFieldRelativeSpeeds(awayFromStation, towardLeftBoundary, - // rotate * SwerveDriveConstants.RotationSpeed, /*get odometry angle*/) - // } + // public void driveFieldRelative(double awayFromStation, double towardLeftBoundary, double rotate) + // { + // var speeds = ChassisSpeeds.fromFieldRelativeSpeeds(awayFromStation, towardLeftBoundary, rotate * SwerveDriveConstants.RotationSpeed, /*get odometry angle*/) + // } } \ No newline at end of file diff --git a/src/main/java/frc4388/robot/subsystems/SwerveModule.java b/src/main/java/frc4388/robot/subsystems/SwerveModule.java index 4726964..7754ef3 100644 --- a/src/main/java/frc4388/robot/subsystems/SwerveModule.java +++ b/src/main/java/frc4388/robot/subsystems/SwerveModule.java @@ -12,22 +12,20 @@ import com.ctre.phoenix.motorcontrol.can.WPI_TalonFX; import com.ctre.phoenix.sensors.CANCoder; import com.ctre.phoenix.sensors.CANCoderConfiguration; -import edu.wpi.first.wpilibj.geometry.Rotation2d; -import edu.wpi.first.wpilibj.kinematics.SwerveModuleState; -import edu.wpi.first.wpilibj.simulation.EncoderSim; -import edu.wpi.first.wpilibj.util.Units; +import edu.wpi.first.math.geometry.Rotation2d; +import edu.wpi.first.math.kinematics.SwerveModuleState; +import edu.wpi.first.math.util.Units; import edu.wpi.first.wpilibj2.command.SubsystemBase; import frc4388.robot.Constants.SwerveDriveConstants; import frc4388.utility.Gains; public class SwerveModule extends SubsystemBase { - private WPI_TalonFX driveMotor; - private WPI_TalonFX angleMotor; - private CANCoder canCoder; - public static Gains m_swerveGains = SwerveDriveConstants.SWERVE_GAINS; - - private static double kEncoderTicksPerRotation = 4096; + private WPI_TalonFX driveMotor; + private WPI_TalonFX angleMotor; + private CANCoder canCoder; + public static Gains m_swerveGains = SwerveDriveConstants.SWERVE_GAINS; + private static double kEncoderTicksPerRotation = 4096; /** Creates a new SwerveModule. */ public SwerveModule(WPI_TalonFX driveMotor, WPI_TalonFX angleMotor, CANCoder canCoder) { @@ -47,30 +45,32 @@ public class SwerveModule extends SubsystemBase { angleTalonFXConfiguration.primaryPID.selectedFeedbackSensor = FeedbackDevice.RemoteSensor0; angleMotor.configAllSettings(angleTalonFXConfiguration); - /*TalonFXConfiguration driveTalonFXConfiguration = new TalonFXConfiguration(); - - driveTalonFXConfiguration.slot0.kP = kDriveP; - driveTalonFXConfiguration.slot0.kI = kDriveI; - driveTalonFXConfiguration.slot0.kD = kDriveD; - driveTalonFXConfiguration.slot0.kF = kDriveF; - - driveMotor.configAllSettings(driveTalonFXConfiguration);*/ + /* + * TalonFXConfiguration driveTalonFXConfiguration = new TalonFXConfiguration(); + * + * driveTalonFXConfiguration.slot0.kP = kDriveP; + * driveTalonFXConfiguration.slot0.kI = kDriveI; + * driveTalonFXConfiguration.slot0.kD = kDriveD; + * driveTalonFXConfiguration.slot0.kF = kDriveF; + * + * driveMotor.configAllSettings(driveTalonFXConfiguration); + */ CANCoderConfiguration canCoderConfiguration = new CANCoderConfiguration(); - //CANCODER CONFIG + // CANCODER CONFIG canCoder.configAllSettings(canCoderConfiguration); } - public Rotation2d getAngle() { - // Note: This assumes the CANCoders are setup with the default feedback coefficient - // and the sesnor value reports degrees. + // Note: This assumes the CANCoders are setup with the default feedback coefficient and the sesnor value reports degrees. return Rotation2d.fromDegrees(canCoder.getAbsolutePosition()); } /** * Set the speed + rotation of the swerve module from a SwerveModuleState object - * @param desiredState - A SwerveModuleState representing the desired new state of the module + * + * @param desiredState - A SwerveModuleState representing the desired new state + * of the module */ public void setDesiredState(SwerveModuleState desiredState) { Rotation2d currentRotation = getAngle(); @@ -86,7 +86,6 @@ public class SwerveModule extends SubsystemBase { double desiredTicks = currentTicks + deltaTicks; angleMotor.set(TalonFXControlMode.Position, desiredTicks); - double feetPerSecond = Units.metersToFeet(state.speedMetersPerSecond); driveMotor.set(angleMotor.get() + feetPerSecond / SwerveDriveConstants.SPEED_FEET_PER_SECOND_AT_FULL_POWER); } diff --git a/src/main/java/frc4388/utility/Gains.java b/src/main/java/frc4388/utility/Gains.java index e3e136f..930e34f 100644 --- a/src/main/java/frc4388/utility/Gains.java +++ b/src/main/java/frc4388/utility/Gains.java @@ -6,55 +6,55 @@ package frc4388.utility; /** Add your docs here. */ public class Gains { - public double m_kP; - public double m_kI; - public double m_kD; - public double m_kF; - public int m_kIzone; - public double m_kPeakOutput; - public double m_kmaxOutput; - public double m_kminOutput; + public double m_kP; + public double m_kI; + public double m_kD; + public double m_kF; + public int m_kIzone; + public double m_kPeakOutput; + public double m_kmaxOutput; + public double m_kminOutput; - /** - * Creates Gains object for PIDs - * @param kP The P value. - * @param kI The I value. - * @param kD The D value. - * @param kF The F value. - * @param kIzone The zone of the I value. - * @param kPeakOutput The peak output setting the motors to run the gains at, in both forward and reverse directions. By default 1.0. - */ - public Gains(double kP, double kI, double kD, double kF, int kIzone, double kPeakOutput) - { - m_kP = kP; - m_kI = kI; - m_kD = kD; - m_kF = kF; - m_kIzone = kIzone; - m_kPeakOutput = kPeakOutput; - m_kmaxOutput = m_kPeakOutput; - m_kminOutput = -m_kPeakOutput; - } + /** + * Creates Gains object for PIDs + * @param kP The P value. + * @param kI The I value. + * @param kD The D value. + * @param kF The F value. + * @param kIzone The zone of the I value. + * @param kPeakOutput The peak output setting the motors to run the gains at, in both forward and reverse directions. By default 1.0. + */ + public Gains(double kP, double kI, double kD, double kF, int kIzone, double kPeakOutput) + { + m_kP = kP; + m_kI = kI; + m_kD = kD; + m_kF = kF; + m_kIzone = kIzone; + m_kPeakOutput = kPeakOutput; + m_kmaxOutput = m_kPeakOutput; + m_kminOutput = -m_kPeakOutput; + } - /** - * Creates Gains object for PIDs - * @param kP The P value. - * @param kI The I value. - * @param kD The D value. - * @param kF The F value. - * @param kIzone The zone of the I value. - * @param kMinOutput The lowest output setting to run the gains at, usually in the reverse direction. By default -1.0. - * @param kMaxOutput The highest output setting to run the gains at, usually in the forward direction. By default 1.0. - */ - public Gains(double kP, double kI, double kD, double kF, int kIzone, double kMinOutput, double kMaxOutput) - { - m_kP = kP; - m_kI = kI; - m_kD = kD; - m_kF = kF; - m_kIzone = kIzone; - m_kminOutput = kMinOutput; - m_kmaxOutput = kMaxOutput; - m_kPeakOutput = (Math.abs(m_kminOutput) > Math.abs(m_kmaxOutput)) ? Math.abs(m_kminOutput) : Math.abs(m_kmaxOutput); - } + /** + * Creates Gains object for PIDs + * @param kP The P value. + * @param kI The I value. + * @param kD The D value. + * @param kF The F value. + * @param kIzone The zone of the I value. + * @param kMinOutput The lowest output setting to run the gains at, usually in the reverse direction. By default -1.0. + * @param kMaxOutput The highest output setting to run the gains at, usually in the forward direction. By default 1.0. + */ + public Gains(double kP, double kI, double kD, double kF, int kIzone, double kMinOutput, double kMaxOutput) + { + m_kP = kP; + m_kI = kI; + m_kD = kD; + m_kF = kF; + m_kIzone = kIzone; + m_kminOutput = kMinOutput; + m_kmaxOutput = kMaxOutput; + m_kPeakOutput = (Math.abs(m_kminOutput) > Math.abs(m_kmaxOutput)) ? Math.abs(m_kminOutput) : Math.abs(m_kmaxOutput); + } } diff --git a/src/main/java/frc4388/utility/RobotGyro.java b/src/main/java/frc4388/utility/RobotGyro.java deleted file mode 100644 index a42e8c8..0000000 --- a/src/main/java/frc4388/utility/RobotGyro.java +++ /dev/null @@ -1,180 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ - -package frc4388.utility; - -import com.ctre.phoenix.sensors.PigeonIMU; -import com.ctre.phoenix.sensors.PigeonIMU.CalibrationMode; -import com.kauailabs.navx.frc.AHRS; - -import edu.wpi.first.wpilibj.GyroBase; -import edu.wpi.first.wpiutil.math.MathUtil; - -/** - * Gyro class that allows for interchangeable use between a pigeon and a navX - */ -public class RobotGyro extends GyroBase { - private RobotTime m_robotTime = RobotTime.getInstance(); - - private PigeonIMU m_pigeon = null; - private AHRS m_navX = null; - public boolean m_isGyroAPigeon; //true if pigeon, false if navX - - private double m_lastPigeonAngle; - private double m_deltaPigeonAngle; - - /** - * Creates a Gyro based on a pigeon - * @param gyro the gyroscope to use for Gyro - */ - public RobotGyro(PigeonIMU gyro) { - m_pigeon = gyro; - m_isGyroAPigeon = true; - } - - /** - * Creates a Gyro based on a navX - * @param gyro the gyroscope to use for Gyro - */ - public RobotGyro(AHRS gyro){ - m_navX = gyro; - m_isGyroAPigeon = false; - } - - /** - * Run in periodic if you are using a pigeon. Updates a delta angle so that it can calculate getRate(). Note - * that the getRate() method for a navX will likely be much more accurate than for a pigeon. - */ - public void updatePigeonDeltas() { - double currentPigeonAngle = getAngle(); - m_deltaPigeonAngle = currentPigeonAngle - m_lastPigeonAngle; - m_lastPigeonAngle = currentPigeonAngle; - } - - /** - *

NavX: - *

Calibrate the gyro by running for a number of samples and computing the center value. Then use - * the center value as the Accumulator center value for subsequent measurements. It's important to - * make sure that the robot is not moving while the centering calculations are in progress, this - * is typically done when the robot is first turned on while it's sitting at rest before the - * competition starts. - * - *

Pigeon: - *

Calibrate the gyro by collecting data at a range of tempuratures. Allow pigeon to cool, then boot - * into calibration mode. For faster calibration, use a heat lamp to heat up the pigeon. Once the pigeon - * has seen a reasonable range of tempuratures, it will exit calibration mode. It's important to - * make sure that the robot is not moving while the tempurature calculations are in progress, this - * is typically done when the robot is first turned on while it's sitting at rest before the - * competition starts. - */ - @Override - public void calibrate() { - if (m_isGyroAPigeon) { - m_pigeon.enterCalibrationMode(CalibrationMode.Temperature); - } else { - m_navX.calibrate(); - } - } - - @Override - public void reset() { - if (m_isGyroAPigeon) { - m_pigeon.setYaw(0); - } else { - m_navX.reset(); - } - } - - /** - * Get Yaw, Pitch, and Roll data. - * - * @return ypr_deg Array with yaw[0], pitch[1], and roll[2] data. - * Yaw is within [-368,640, +368,640] degrees. - * Pitch is within [-90,+90] degrees. - * Roll is within [-90,+90] degrees. - */ - private double[] getPigeonAngles() { - double[] angles = new double[3]; - m_pigeon.getYawPitchRoll(angles); - return angles; - } - - @Override - public double getAngle() { - if (m_isGyroAPigeon) { - return getPigeonAngles()[0]; - } else { - return m_navX.getAngle(); - } - } - - /** - * Gets an absolute heading of the robot - * @return heading from -180 to 180 degrees - */ - public double getHeading() { - return getHeading(getAngle()); - } - - /** - * Gets an absolute heading of the robot - * @return heading from -180 to 180 degrees - */ - public double getHeading(double angle) { - return Math.IEEEremainder(angle, 360); - } - - /** - * Returns the current pitch value (in degrees, from -90 to 90) - * reported by the sensor. Pitch is a measure of rotation around - * the Y Axis. - * @return The current pitch value in degrees (-90 to 90). - */ - public double getPitch() { - if (m_isGyroAPigeon) { - return MathUtil.clamp(getPigeonAngles()[1], -90, 90); - } else { - return MathUtil.clamp(m_navX.getPitch(), -90, 90); - } - } - - /** - * Returns the current roll value (in degrees, from -90 to 90) - * reported by the sensor. Roll is a measure of rotation around - * the X Axis. - * @return The current roll value in degrees (-90 to 90). - */ - public double getRoll() { - if (m_isGyroAPigeon) { - return MathUtil.clamp(getPigeonAngles()[2], -90, 90); - } else { - return MathUtil.clamp(m_navX.getRoll(), -90, 90); - } - } - - @Override - public double getRate() { - if (m_isGyroAPigeon) { - return m_deltaPigeonAngle / m_robotTime.m_deltaTime * 1000; - } else { - return m_navX.getRate(); - } - } - - public PigeonIMU getPigeon(){ - return m_pigeon; - } - - public AHRS getNavX(){ - return m_navX; - } - - @Override - public void close() throws Exception { - - } -} diff --git a/src/main/java/frc4388/utility/RobotGyro.java.old b/src/main/java/frc4388/utility/RobotGyro.java.old new file mode 100644 index 0000000..56390d4 --- /dev/null +++ b/src/main/java/frc4388/utility/RobotGyro.java.old @@ -0,0 +1,245 @@ +// 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 frc4388.utility; + +import com.ctre.phoenix.sensors.PigeonIMU; +import com.ctre.phoenix.sensors.PigeonIMU.CalibrationMode; +import com.kauailabs.navx.frc.AHRS; + +import edu.wpi.first.math.MathUtil; +import edu.wpi.first.util.sendable.Sendable; +import edu.wpi.first.util.sendable.SendableBuilder; +import edu.wpi.first.wpilibj.PIDSource; +import edu.wpi.first.wpilibj.PIDSourceType; +import edu.wpi.first.wpilibj.interfaces.Gyro; + +/** + * Gyro class that allows for interchangeable use between a pigeon and a navX + */ +public class RobotGyro implements Gyro, PIDSource, Sendable { + private RobotTime m_robotTime = RobotTime.getInstance(); + + private PigeonIMU m_pigeon = null; + private AHRS m_navX = null; + public boolean m_isGyroAPigeon; // true if pigeon, false if navX + + private double m_lastPigeonAngle; + private double m_deltaPigeonAngle; + + /** + * Creates a Gyro based on a pigeon + * + * @param gyro the gyroscope to use for Gyro + */ + public RobotGyro(PigeonIMU gyro) { + m_pigeon = gyro; + m_isGyroAPigeon = true; + } + + /** + * Creates a Gyro based on a navX + * + * @param gyro the gyroscope to use for Gyro + */ + public RobotGyro(AHRS gyro) { + m_navX = gyro; + m_isGyroAPigeon = false; + } + + /** + * Run in periodic if you are using a pigeon. Updates a delta angle so that it + * can calculate getRate(). Note + * that the getRate() method for a navX will likely be much more accurate than + * for a pigeon. + */ + public void updatePigeonDeltas() { + double currentPigeonAngle = getAngle(); + m_deltaPigeonAngle = currentPigeonAngle - m_lastPigeonAngle; + m_lastPigeonAngle = currentPigeonAngle; + } + + /** + *

+ * NavX: + *

+ * Calibrate the gyro by running for a number of samples and computing the + * center value. Then use + * the center value as the Accumulator center value for subsequent measurements. + * It's important to + * make sure that the robot is not moving while the centering calculations are + * in progress, this + * is typically done when the robot is first turned on while it's sitting at + * rest before the + * competition starts. + * + *

+ * Pigeon: + *

+ * Calibrate the gyro by collecting data at a range of tempuratures. Allow + * pigeon to cool, then boot + * into calibration mode. For faster calibration, use a heat lamp to heat up the + * pigeon. Once the pigeon + * has seen a reasonable range of tempuratures, it will exit calibration mode. + * It's important to + * make sure that the robot is not moving while the tempurature calculations are + * in progress, this + * is typically done when the robot is first turned on while it's sitting at + * rest before the + * competition starts. + */ + @Override + public void calibrate() { + if (m_isGyroAPigeon) + m_pigeon.enterCalibrationMode(CalibrationMode.Temperature); + else + m_navX.calibrate(); + } + + @Override + public void reset() { + if (m_isGyroAPigeon) + m_pigeon.setYaw(0); + else + m_navX.reset(); + } + + /** + * Get Yaw, Pitch, and Roll data. + * + * @return ypr_deg Array with yaw[0], pitch[1], and roll[2] data. + * Yaw is within [-368,640, +368,640] degrees. + * Pitch is within [-90,+90] degrees. + * Roll is within [-90,+90] degrees. + */ + private double[] getPigeonAngles() { + double[] angles = new double[3]; + m_pigeon.getYawPitchRoll(angles); + return angles; + } + + @Override + public double getAngle() { + if (m_isGyroAPigeon) { + return getPigeonAngles()[0]; + } else { + return m_navX.getAngle(); + } + } + + /** + * Gets an absolute heading of the robot + * + * @return heading from -180 to 180 degrees + */ + public double getHeading() { + return getHeading(getAngle()); + } + + /** + * Gets an absolute heading of the robot + * + * @return heading from -180 to 180 degrees + */ + public double getHeading(double angle) { + return Math.IEEEremainder(angle, 360); + } + + /** + * Returns the current pitch value (in degrees, from -90 to 90) + * reported by the sensor. Pitch is a measure of rotation around + * the Y Axis. + * + * @return The current pitch value in degrees (-90 to 90). + */ + public double getPitch() { + if (m_isGyroAPigeon) { + return MathUtil.clamp(getPigeonAngles()[1], -90, 90); + } else { + return MathUtil.clamp(m_navX.getPitch(), -90, 90); + } + } + + /** + * Returns the current roll value (in degrees, from -90 to 90) + * reported by the sensor. Roll is a measure of rotation around + * the X Axis. + * + * @return The current roll value in degrees (-90 to 90). + */ + public double getRoll() { + if (m_isGyroAPigeon) { + return MathUtil.clamp(getPigeonAngles()[2], -90, 90); + } else { + return MathUtil.clamp(m_navX.getRoll(), -90, 90); + } + } + + @Override + public double getRate() { + if (m_isGyroAPigeon) { + return m_deltaPigeonAngle / m_robotTime.m_deltaTime * 1000; + } else { + return m_navX.getRate(); + } + } + + public PigeonIMU getPigeon() { + return m_pigeon; + } + + public AHRS getNavX() { + return m_navX; + } + + @Override + public void close() throws Exception { + + } + + // Begin old GyroBase class + private PIDSourceType m_pidSource = PIDSourceType.kDisplacement; + + /** + * Set which parameter of the gyro you are using as a process control variable. + * The Gyro class + * supports the rate and displacement parameters + * + * @param pidSource An enum to select the parameter. + */ + @Override + public void setPIDSourceType(PIDSourceType pidSource) { + m_pidSource = pidSource; + } + + @Override + public PIDSourceType getPIDSourceType() { + return m_pidSource; + } + + /** + * Get the output of the gyro for use with PIDControllers. May be the angle or + * rate depending on + * the set PIDSourceType + * + * @return the output according to the gyro + */ + @Override + public double pidGet() { + switch (m_pidSource) { + case kRate: + return getRate(); + case kDisplacement: + return getAngle(); + default: + return 0.0; + } + } + + @Override + public void initSendable(SendableBuilder builder) { + builder.setSmartDashboardType("Gyro"); + builder.addDoubleProperty("Value", this::getAngle, null); + } +} diff --git a/src/main/java/frc4388/utility/RobotTime.java b/src/main/java/frc4388/utility/RobotTime.java index 694f850..5bda50f 100644 --- a/src/main/java/frc4388/utility/RobotTime.java +++ b/src/main/java/frc4388/utility/RobotTime.java @@ -1,9 +1,6 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ +// 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 frc4388.utility; @@ -12,68 +9,68 @@ package frc4388.utility; *

All times are in milliseconds */ public class RobotTime { - private long m_currTime = System.currentTimeMillis(); - public long m_deltaTime = 0; + private long m_currTime = System.currentTimeMillis(); + public long m_deltaTime = 0; - private long m_startRobotTime = m_currTime; - public long m_robotTime = 0; - public long m_lastRobotTime = 0; + private long m_startRobotTime = m_currTime; + public long m_robotTime = 0; + public long m_lastRobotTime = 0; - private long m_startMatchTime = 0; - public long m_matchTime = 0; - public long m_lastMatchTime = 0; + private long m_startMatchTime = 0; + public long m_matchTime = 0; + public long m_lastMatchTime = 0; - public long m_frameNumber = 0; + public long m_frameNumber = 0; - /** - * Private constructor prevents other classes from instantiating - */ - private RobotTime(){} + /** + * Private constructor prevents other classes from instantiating + */ + private RobotTime(){} - private static RobotTime instance = null; + private static RobotTime instance = null; - /** - * Gets the instance of Robot Time. If there is no instance running one will be created. - * @return instance of Robot Time - */ - public static RobotTime getInstance() { - if (instance == null) { - instance = new RobotTime(); - } - return instance; + /** + * Gets the instance of Robot Time. If there is no instance running one will be created. + * @return instance of Robot Time + */ + public static RobotTime getInstance() { + if (instance == null) { + instance = new RobotTime(); } + return instance; + } - /** - * Call this once per periodic loop. - */ - public void updateTimes() { - m_lastRobotTime = m_robotTime; - m_lastMatchTime = m_matchTime; + /** + * Call this once per periodic loop. + */ + public void updateTimes() { + m_lastRobotTime = m_robotTime; + m_lastMatchTime = m_matchTime; - m_currTime = System.currentTimeMillis(); - m_robotTime = m_currTime - m_startRobotTime; - m_deltaTime = m_robotTime - m_lastRobotTime; - m_frameNumber++; + m_currTime = System.currentTimeMillis(); + m_robotTime = m_currTime - m_startRobotTime; + m_deltaTime = m_robotTime - m_lastRobotTime; + m_frameNumber++; - if (m_startMatchTime != 0) { - m_matchTime = m_currTime - m_startMatchTime; - } + if (m_startMatchTime != 0) { + m_matchTime = m_currTime - m_startMatchTime; } + } - /** - * Call this in both the auto and periodic inits - */ - public void startMatchTime() { - if (m_startMatchTime == 0) { - m_startMatchTime = m_currTime; - } + /** + * Call this in both the auto and periodic inits + */ + public void startMatchTime() { + if (m_startMatchTime == 0) { + m_startMatchTime = m_currTime; } + } - /** - * Call this in disabled init - */ - public void endMatchTime() { - m_startMatchTime = 0; - m_matchTime = 0; - } + /** + * Call this in disabled init + */ + public void endMatchTime() { + m_startMatchTime = 0; + m_matchTime = 0; + } } diff --git a/src/main/java/frc4388/utility/controller/IHandController.java b/src/main/java/frc4388/utility/controller/IHandController.java index 13aa763..319aebc 100644 --- a/src/main/java/frc4388/utility/controller/IHandController.java +++ b/src/main/java/frc4388/utility/controller/IHandController.java @@ -5,17 +5,17 @@ package frc4388.utility.controller; */ public interface IHandController { - public double getLeftXAxis(); + public double getLeftXAxis(); - public double getLeftYAxis(); + public double getLeftYAxis(); - public double getRightXAxis(); - - public double getRightYAxis(); + public double getRightXAxis(); - public double getLeftTriggerAxis(); + public double getRightYAxis(); - public double getRightTriggerAxis(); + public double getLeftTriggerAxis(); - public int getDpadAngle(); + public double getRightTriggerAxis(); + + public int getDpadAngle(); } diff --git a/src/main/java/frc4388/utility/controller/XboxController.java b/src/main/java/frc4388/utility/controller/XboxController.java index 8b8f0f8..25c496a 100644 --- a/src/main/java/frc4388/utility/controller/XboxController.java +++ b/src/main/java/frc4388/utility/controller/XboxController.java @@ -9,210 +9,210 @@ import edu.wpi.first.wpilibj.Joystick; */ public class XboxController implements IHandController { - public static final int LEFT_X_AXIS = 0; - public static final int LEFT_Y_AXIS = 1; - public static final int LEFT_TRIGGER_AXIS = 2; - public static final int RIGHT_TRIGGER_AXIS = 3; - public static final int RIGHT_X_AXIS = 4; - public static final int RIGHT_Y_AXIS = 5; - public static final int LEFT_RIGHT_DPAD_AXIS = 6; - public static final int TOP_BOTTOM_DPAD_AXIS = 6; + public static final int LEFT_X_AXIS = 0; + public static final int LEFT_Y_AXIS = 1; + public static final int LEFT_TRIGGER_AXIS = 2; + public static final int RIGHT_TRIGGER_AXIS = 3; + public static final int RIGHT_X_AXIS = 4; + public static final int RIGHT_Y_AXIS = 5; + public static final int LEFT_RIGHT_DPAD_AXIS = 6; + public static final int TOP_BOTTOM_DPAD_AXIS = 6; - public static final int A_BUTTON = 1; - public static final int B_BUTTON = 2; - public static final int X_BUTTON = 3; - public static final int Y_BUTTON = 4; - public static final int LEFT_BUMPER_BUTTON = 5; - public static final int RIGHT_BUMPER_BUTTON = 6; - public static final int BACK_BUTTON = 7; - public static final int START_BUTTON = 8; + public static final int A_BUTTON = 1; + public static final int B_BUTTON = 2; + public static final int X_BUTTON = 3; + public static final int Y_BUTTON = 4; + public static final int LEFT_BUMPER_BUTTON = 5; + public static final int RIGHT_BUMPER_BUTTON = 6; + public static final int BACK_BUTTON = 7; + public static final int START_BUTTON = 8; - public static final int LEFT_JOYSTICK_BUTTON = 9; - public static final int RIGHT_JOYSTICK_BUTTON = 10; + public static final int LEFT_JOYSTICK_BUTTON = 9; + public static final int RIGHT_JOYSTICK_BUTTON = 10; - private static final double LEFT_DPAD_TOLERANCE = -0.9; - private static final double RIGHT_DPAD_TOLERANCE = 0.9; - private static final double BOTTOM_DPAD_TOLERANCE = -0.9; - private static final double TOP_DPAD_TOLERANCE = 0.9; + private static final double LEFT_DPAD_TOLERANCE = -0.9; + private static final double RIGHT_DPAD_TOLERANCE = 0.9; + private static final double BOTTOM_DPAD_TOLERANCE = -0.9; + private static final double TOP_DPAD_TOLERANCE = 0.9; - private static final double LEFT_TRIGGER_TOLERANCE = 0.5; - private static final double RIGHT_TRIGGER_TOLERANCE = 0.5; + private static final double LEFT_TRIGGER_TOLERANCE = 0.5; + private static final double RIGHT_TRIGGER_TOLERANCE = 0.5; - private static final double RIGHT_AXIS_UP_TOLERANCE = -0.9; - private static final double RIGHT_AXIS_DOWN_TOLERANCE = 0.9; - private static final double RIGHT_AXIS_RIGHT_TOLERANCE = 0.9; - private static final double RIGHT_AXIS_LEFT_TOLERANCE = -0.9; + private static final double RIGHT_AXIS_UP_TOLERANCE = -0.9; + private static final double RIGHT_AXIS_DOWN_TOLERANCE = 0.9; + private static final double RIGHT_AXIS_RIGHT_TOLERANCE = 0.9; + private static final double RIGHT_AXIS_LEFT_TOLERANCE = -0.9; - private static final double LEFT_AXIS_UP_TOLERANCE = -0.9; - private static final double LEFT_AXIS_DOWN_TOLERANCE = 0.9; - private static final double LEFT_AXIS_RIGHT_TOLERANCE = 0.9; - private static final double LEFT_AXIS_LEFT_TOLERANCE = -0.9; + private static final double LEFT_AXIS_UP_TOLERANCE = -0.9; + private static final double LEFT_AXIS_DOWN_TOLERANCE = 0.9; + private static final double LEFT_AXIS_RIGHT_TOLERANCE = 0.9; + private static final double LEFT_AXIS_LEFT_TOLERANCE = -0.9; - private static final double DEADZONE = 0.1; + private static final double DEADZONE = 0.1; - private Joystick m_stick; + private Joystick m_stick; - /** + /** * Add your docs here. */ - public XboxController(int portNumber){ - m_stick = new Joystick(portNumber); - } + public XboxController(int portNumber){ + m_stick = new Joystick(portNumber); + } - /** + /** * Add your docs here. */ - public Joystick getJoyStick() { - return m_stick; - } - - /** - * Checks if the input falls within the deadzone. - * @param input from an axis on the controller - * @return true if input falls in deadzone, false if input falls outside deadzone - */ - private boolean inDeadZone(double input){ - return (Math.abs(input) < DEADZONE); - } + public Joystick getJoyStick() { + return m_stick; + } + + /** + * Checks if the input falls within the deadzone. + * @param input from an axis on the controller + * @return true if input falls in deadzone, false if input falls outside deadzone + */ + private boolean inDeadZone(double input){ + return (Math.abs(input) < DEADZONE); + } - /** - * Updates an input to have a deadzone around the 0 position - * @param input from an axis on the controller - * @return updated input - */ - private double getAxisWithDeadZoneCheck(double input){ - if(inDeadZone(input)){ - return 0.0; - } else { - return input; - } - } + /** + * Updates an input to have a deadzone around the 0 position + * @param input from an axis on the controller + * @return updated input + */ + private double getAxisWithDeadZoneCheck(double input){ + if(inDeadZone(input)){ + return 0.0; + } else { + return input; + } + } - public boolean getAButton(){ - return m_stick.getRawButton(A_BUTTON); - } + public boolean getAButton(){ + return m_stick.getRawButton(A_BUTTON); + } - public boolean getXButton(){ - return m_stick.getRawButton(X_BUTTON); - } + public boolean getXButton(){ + return m_stick.getRawButton(X_BUTTON); + } - public boolean getBButton(){ - return m_stick.getRawButton(B_BUTTON); - } + public boolean getBButton(){ + return m_stick.getRawButton(B_BUTTON); + } - public boolean getYButton(){ - return m_stick.getRawButton(Y_BUTTON); - } + public boolean getYButton(){ + return m_stick.getRawButton(Y_BUTTON); + } - public boolean getBackButton(){ - return m_stick.getRawButton(BACK_BUTTON); - } + public boolean getBackButton(){ + return m_stick.getRawButton(BACK_BUTTON); + } - public boolean getStartButton(){ - return m_stick.getRawButton(START_BUTTON); - } + public boolean getStartButton(){ + return m_stick.getRawButton(START_BUTTON); + } - public boolean getLeftBumperButton(){ - return m_stick.getRawButton(LEFT_BUMPER_BUTTON); - } + public boolean getLeftBumperButton(){ + return m_stick.getRawButton(LEFT_BUMPER_BUTTON); + } - public boolean getRightBumperButton(){ - return m_stick.getRawButton(RIGHT_BUMPER_BUTTON); - } + public boolean getRightBumperButton(){ + return m_stick.getRawButton(RIGHT_BUMPER_BUTTON); + } - public boolean getLeftJoystickButton(){ - return m_stick.getRawButton(LEFT_JOYSTICK_BUTTON); - } + public boolean getLeftJoystickButton(){ + return m_stick.getRawButton(LEFT_JOYSTICK_BUTTON); + } - public boolean getRightJoystickButton(){ - return m_stick.getRawButton(RIGHT_JOYSTICK_BUTTON); - } + public boolean getRightJoystickButton(){ + return m_stick.getRawButton(RIGHT_JOYSTICK_BUTTON); + } - public double getLeftXAxis(){ - return getAxisWithDeadZoneCheck(m_stick.getRawAxis(LEFT_X_AXIS)); - } + public double getLeftXAxis(){ + return getAxisWithDeadZoneCheck(m_stick.getRawAxis(LEFT_X_AXIS)); + } - public double getLeftYAxis(){ - return getAxisWithDeadZoneCheck(m_stick.getRawAxis(LEFT_Y_AXIS)); - } + public double getLeftYAxis(){ + return getAxisWithDeadZoneCheck(m_stick.getRawAxis(LEFT_Y_AXIS)); + } - public double getRightXAxis(){ - return getAxisWithDeadZoneCheck(m_stick.getRawAxis(RIGHT_X_AXIS)); - } + public double getRightXAxis(){ + return getAxisWithDeadZoneCheck(m_stick.getRawAxis(RIGHT_X_AXIS)); + } - public double getRightYAxis(){ - return getAxisWithDeadZoneCheck(m_stick.getRawAxis(RIGHT_Y_AXIS)); - } + public double getRightYAxis(){ + return getAxisWithDeadZoneCheck(m_stick.getRawAxis(RIGHT_Y_AXIS)); + } - public double getLeftTriggerAxis(){ - return getAxisWithDeadZoneCheck(m_stick.getRawAxis(LEFT_TRIGGER_AXIS)); - } + public double getLeftTriggerAxis(){ + return getAxisWithDeadZoneCheck(m_stick.getRawAxis(LEFT_TRIGGER_AXIS)); + } - public double getRightTriggerAxis(){ - return getAxisWithDeadZoneCheck(m_stick.getRawAxis(RIGHT_TRIGGER_AXIS)); - } + public double getRightTriggerAxis(){ + return getAxisWithDeadZoneCheck(m_stick.getRawAxis(RIGHT_TRIGGER_AXIS)); + } - /** - * Get the angle input from the dpad. - * @return -1 if nothing is pressed, or the angle of the button pressed. 0 = up, 90 = right, etc. - */ - public int getDpadAngle() { - return m_stick.getPOV(0); - } + /** + * Get the angle input from the dpad. + * @return -1 if nothing is pressed, or the angle of the button pressed. 0 = up, 90 = right, etc. + */ + public int getDpadAngle() { + return m_stick.getPOV(0); + } - public boolean getDPadLeft(){ + public boolean getDPadLeft(){ return (m_stick.getRawAxis(LEFT_RIGHT_DPAD_AXIS) < LEFT_DPAD_TOLERANCE); - } + } - public boolean getDPadRight(){ + public boolean getDPadRight(){ return (m_stick.getRawAxis(LEFT_RIGHT_DPAD_AXIS) > RIGHT_DPAD_TOLERANCE); - } + } - public boolean getDPadTop(){ + public boolean getDPadTop(){ return (m_stick.getRawAxis(TOP_BOTTOM_DPAD_AXIS) < TOP_DPAD_TOLERANCE); - } + } - public boolean getDPadBottom(){ + public boolean getDPadBottom(){ return (m_stick.getRawAxis(TOP_BOTTOM_DPAD_AXIS) > BOTTOM_DPAD_TOLERANCE); - } + } - public boolean getLeftTrigger(){ - return (getLeftTriggerAxis() > LEFT_TRIGGER_TOLERANCE); - } + public boolean getLeftTrigger(){ + return (getLeftTriggerAxis() > LEFT_TRIGGER_TOLERANCE); + } - public boolean getRightTrigger(){ - return (getRightTriggerAxis() > RIGHT_TRIGGER_TOLERANCE); - } + public boolean getRightTrigger(){ + return (getRightTriggerAxis() > RIGHT_TRIGGER_TOLERANCE); + } - public boolean getRightAxisUpTrigger(){ - return (getRightYAxis() < RIGHT_AXIS_UP_TOLERANCE); - } + public boolean getRightAxisUpTrigger(){ + return (getRightYAxis() < RIGHT_AXIS_UP_TOLERANCE); + } - public boolean getRightAxisDownTrigger(){ - return (getRightYAxis() > RIGHT_AXIS_DOWN_TOLERANCE); - } + public boolean getRightAxisDownTrigger(){ + return (getRightYAxis() > RIGHT_AXIS_DOWN_TOLERANCE); + } - public boolean getRightAxisLeftTrigger(){ - return (getRightXAxis() > RIGHT_AXIS_LEFT_TOLERANCE); - } + public boolean getRightAxisLeftTrigger(){ + return (getRightXAxis() > RIGHT_AXIS_LEFT_TOLERANCE); + } - public boolean getRightAxisRightTrigger(){ - return (getRightXAxis() > RIGHT_AXIS_RIGHT_TOLERANCE); - } + public boolean getRightAxisRightTrigger(){ + return (getRightXAxis() > RIGHT_AXIS_RIGHT_TOLERANCE); + } - public boolean getLeftAxisUpTrigger(){ - return (getLeftYAxis() < LEFT_AXIS_UP_TOLERANCE); - } + public boolean getLeftAxisUpTrigger(){ + return (getLeftYAxis() < LEFT_AXIS_UP_TOLERANCE); + } - public boolean getLeftAxisDownTrigger(){ - return (getLeftYAxis() > LEFT_AXIS_DOWN_TOLERANCE); - } + public boolean getLeftAxisDownTrigger(){ + return (getLeftYAxis() > LEFT_AXIS_DOWN_TOLERANCE); + } - public boolean getLeftAxisLeftTrigger(){ - return (getLeftXAxis() > LEFT_AXIS_LEFT_TOLERANCE); - } + public boolean getLeftAxisLeftTrigger(){ + return (getLeftXAxis() > LEFT_AXIS_LEFT_TOLERANCE); + } - public boolean getLeftAxisRightTrigger(){ - return (getLeftXAxis() > LEFT_AXIS_RIGHT_TOLERANCE); - } + public boolean getLeftAxisRightTrigger(){ + return (getLeftXAxis() > LEFT_AXIS_RIGHT_TOLERANCE); + } } \ No newline at end of file diff --git a/src/main/java/frc4388/utility/controller/XboxTriggerButton.java b/src/main/java/frc4388/utility/controller/XboxTriggerButton.java index 26372c2..cecf379 100644 --- a/src/main/java/frc4388/utility/controller/XboxTriggerButton.java +++ b/src/main/java/frc4388/utility/controller/XboxTriggerButton.java @@ -1,7 +1,6 @@ package frc4388.utility.controller; import edu.wpi.first.wpilibj2.command.button.Button; -import frc4388.utility.controller.XboxController; /** * Mapping for the Xbox controller triggers to allow triggers to be defined as @@ -9,61 +8,43 @@ import frc4388.utility.controller.XboxController; * exceeds a tolerance defined in {@link XboxController}. */ public class XboxTriggerButton extends Button { - public static final int RIGHT_TRIGGER = 0; - public static final int LEFT_TRIGGER = 1; - public static final int RIGHT_AXIS_UP_TRIGGER = 2; - public static final int RIGHT_AXIS_DOWN_TRIGGER = 3; - public static final int RIGHT_AXIS_RIGHT_TRIGGER = 4; - public static final int RIGHT_AXIS_LEFT_TRIGGER = 5; - public static final int LEFT_AXIS_UP_TRIGGER = 6; - public static final int LEFT_AXIS_DOWN_TRIGGER = 7; - public static final int LEFT_AXIS_RIGHT_TRIGGER = 8; - public static final int LEFT_AXIS_LEFT_TRIGGER = 9; + public static final int RIGHT_TRIGGER = 0; + public static final int LEFT_TRIGGER = 1; + public static final int RIGHT_AXIS_UP_TRIGGER = 2; + public static final int RIGHT_AXIS_DOWN_TRIGGER = 3; + public static final int RIGHT_AXIS_RIGHT_TRIGGER = 4; + public static final int RIGHT_AXIS_LEFT_TRIGGER = 5; + public static final int LEFT_AXIS_UP_TRIGGER = 6; + public static final int LEFT_AXIS_DOWN_TRIGGER = 7; + public static final int LEFT_AXIS_RIGHT_TRIGGER = 8; + public static final int LEFT_AXIS_LEFT_TRIGGER = 9; - private XboxController m_controller; - private int m_trigger; + private XboxController m_controller; + private int m_trigger; - /** - * Creates a Trigger-Button mapped to a specific Xbox controller and trigger - */ - public XboxTriggerButton(XboxController controller, int trigger) { - m_controller = controller; - m_trigger = trigger; - } + /** + * Creates a Trigger-Button mapped to a specific Xbox controller and trigger + */ + public XboxTriggerButton(XboxController controller, int trigger) { + m_controller = controller; + m_trigger = trigger; + } - /** {@inheritDoc} */ - @Override - public boolean get() { - if (m_trigger == RIGHT_TRIGGER) { - return m_controller.getRightTrigger(); - } - else if (m_trigger == LEFT_TRIGGER) { - return m_controller.getLeftTrigger(); - } - else if (m_trigger == RIGHT_AXIS_UP_TRIGGER) { - return m_controller.getRightAxisUpTrigger(); - } - else if (m_trigger == RIGHT_AXIS_DOWN_TRIGGER) { - return m_controller.getRightAxisDownTrigger(); - } - else if (m_trigger == RIGHT_AXIS_RIGHT_TRIGGER) { - return m_controller.getRightAxisRightTrigger(); - } - else if (m_trigger == RIGHT_AXIS_LEFT_TRIGGER) { - return m_controller.getRightAxisLeftTrigger(); - } - else if (m_trigger == LEFT_AXIS_UP_TRIGGER) { - return m_controller.getLeftAxisUpTrigger(); - } - else if (m_trigger == LEFT_AXIS_DOWN_TRIGGER) { - return m_controller.getLeftAxisDownTrigger(); - } - else if (m_trigger == LEFT_AXIS_RIGHT_TRIGGER) { - return m_controller.getLeftAxisRightTrigger(); - } - else if (m_trigger == LEFT_AXIS_LEFT_TRIGGER) { - return m_controller.getLeftAxisLeftTrigger(); - } - return false; - } + /** {@inheritDoc} */ + @Override + public boolean get() { + switch (m_trigger) { + case RIGHT_TRIGGER: return m_controller.getRightTrigger(); + case LEFT_TRIGGER: return m_controller.getLeftTrigger(); + case RIGHT_AXIS_UP_TRIGGER: return m_controller.getRightAxisUpTrigger(); + case RIGHT_AXIS_DOWN_TRIGGER: return m_controller.getRightAxisDownTrigger(); + case RIGHT_AXIS_RIGHT_TRIGGER: return m_controller.getRightAxisRightTrigger(); + case RIGHT_AXIS_LEFT_TRIGGER: return m_controller.getRightAxisLeftTrigger(); + case LEFT_AXIS_UP_TRIGGER: return m_controller.getLeftAxisUpTrigger(); + case LEFT_AXIS_DOWN_TRIGGER: return m_controller.getLeftAxisDownTrigger(); + case LEFT_AXIS_RIGHT_TRIGGER: return m_controller.getLeftAxisRightTrigger(); + case LEFT_AXIS_LEFT_TRIGGER: return m_controller.getLeftAxisLeftTrigger(); + default: return false; + } + } } diff --git a/src/test/java/frc4388/mocks/MockPigeonIMU.java b/src/test/java/frc4388/mocks/MockPigeonIMU.java index ecddde7..d054a72 100644 --- a/src/test/java/frc4388/mocks/MockPigeonIMU.java +++ b/src/test/java/frc4388/mocks/MockPigeonIMU.java @@ -1,9 +1,6 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ +// 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 frc4388.mocks; @@ -14,41 +11,41 @@ import com.ctre.phoenix.sensors.PigeonIMU; * Add your docs here. */ public class MockPigeonIMU extends PigeonIMU { - public int m_deviceNumber; - public double currentYaw; - public double currentPitch; - public double currentRoll; + public int m_deviceNumber; + public double currentYaw; + public double currentPitch; + public double currentRoll; - public MockPigeonIMU(int deviceNumber) { - super(deviceNumber); - m_deviceNumber = deviceNumber; - } + public MockPigeonIMU(int deviceNumber) { + super(deviceNumber); + m_deviceNumber = deviceNumber; + } - @Override - public ErrorCode setYaw(double angleDeg) { - currentYaw = angleDeg; - return ErrorCode.OK; - } + @Override + public ErrorCode setYaw(double angleDeg) { + currentYaw = angleDeg; + return ErrorCode.OK; + } - /** - * @param currentPitch the Pitch to set - */ - public void setCurrentPitch(double currentPitch) { - this.currentPitch = currentPitch; - } + /** + * @param currentPitch the Pitch to set + */ + public void setCurrentPitch(double currentPitch) { + this.currentPitch = currentPitch; + } - /** - * @param currentRoll the Roll to set - */ - public void setCurrentRoll(double currentRoll) { - this.currentRoll = currentRoll; - } + /** + * @param currentRoll the Roll to set + */ + public void setCurrentRoll(double currentRoll) { + this.currentRoll = currentRoll; + } - @Override - public ErrorCode getYawPitchRoll(double[] ypr_deg) { - ypr_deg[0] = currentYaw; - ypr_deg[1] = currentPitch; - ypr_deg[2] = currentRoll; - return ErrorCode.OK; - } + @Override + public ErrorCode getYawPitchRoll(double[] ypr_deg) { + ypr_deg[0] = currentYaw; + ypr_deg[1] = currentPitch; + ypr_deg[2] = currentRoll; + return ErrorCode.OK; + } } diff --git a/src/test/java/frc4388/robot/subsystems/LEDSubsystemTest.java b/src/test/java/frc4388/robot/subsystems/LEDSubsystemTest.java index 8fcbf53..87ab85c 100644 --- a/src/test/java/frc4388/robot/subsystems/LEDSubsystemTest.java +++ b/src/test/java/frc4388/robot/subsystems/LEDSubsystemTest.java @@ -1,9 +1,6 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ +// 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 frc4388.robot.subsystems; @@ -12,7 +9,7 @@ import static org.mockito.Mockito.mock; import org.junit.Test; -import edu.wpi.first.wpilibj.*; +import edu.wpi.first.wpilibj.motorcontrol.Spark; import frc4388.robot.Constants.LEDConstants; import frc4388.utility.LEDPatterns; @@ -20,40 +17,40 @@ import frc4388.utility.LEDPatterns; * Add your docs here. */ public class LEDSubsystemTest { - @Test - public void testConstructor() { - // Arrange - Spark ledController = mock(Spark.class); + @Test + public void testConstructor() { + // Arrange + Spark ledController = mock(Spark.class); - // Act - LED led = new LED(ledController); + // Act + LED led = new LED(ledController); - // Assert - assertEquals(LEDConstants.DEFAULT_PATTERN.getValue(), led.getPattern().getValue(), 0.0001); - } + // Assert + assertEquals(LEDConstants.DEFAULT_PATTERN.getValue(), led.getPattern().getValue(), 0.0001); + } - @Test - public void testPatterns() { - // Arrange - Spark ledController = mock(Spark.class); - LED led = new LED(ledController); + @Test + public void testPatterns() { + // Arrange + Spark ledController = mock(Spark.class); + LED led = new LED(ledController); - // Act - led.setPattern(LEDPatterns.RAINBOW_RAINBOW); + // Act + led.setPattern(LEDPatterns.RAINBOW_RAINBOW); - // Assert - assertEquals(LEDPatterns.RAINBOW_RAINBOW.getValue(), led.getPattern().getValue(), 0.0001); + // Assert + assertEquals(LEDPatterns.RAINBOW_RAINBOW.getValue(), led.getPattern().getValue(), 0.0001); - // Act - led.setPattern(LEDPatterns.BLUE_BREATH); + // Act + led.setPattern(LEDPatterns.BLUE_BREATH); - // Assert - assertEquals(LEDPatterns.BLUE_BREATH.getValue(), led.getPattern().getValue(), 0.0001); + // Assert + assertEquals(LEDPatterns.BLUE_BREATH.getValue(), led.getPattern().getValue(), 0.0001); - // Act - led.setPattern(LEDPatterns.SOLID_BLACK); + // Act + led.setPattern(LEDPatterns.SOLID_BLACK); - // Assert - assertEquals(LEDPatterns.SOLID_BLACK.getValue(), led.getPattern().getValue(), 0.0001); - } + // Assert + assertEquals(LEDPatterns.SOLID_BLACK.getValue(), led.getPattern().getValue(), 0.0001); + } } diff --git a/src/test/java/frc4388/utility/RobotGyroUtilityTest.java b/src/test/java/frc4388/utility/RobotGyroUtilityTest.java.old similarity index 91% rename from src/test/java/frc4388/utility/RobotGyroUtilityTest.java rename to src/test/java/frc4388/utility/RobotGyroUtilityTest.java.old index c6f0433..862da0e 100644 --- a/src/test/java/frc4388/utility/RobotGyroUtilityTest.java +++ b/src/test/java/frc4388/utility/RobotGyroUtilityTest.java.old @@ -1,9 +1,6 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ +// 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 frc4388.utility; diff --git a/src/test/java/frc4388/utility/RobotTimeUtilityTest.java b/src/test/java/frc4388/utility/RobotTimeUtilityTest.java index 2c31a34..cc96d41 100644 --- a/src/test/java/frc4388/utility/RobotTimeUtilityTest.java +++ b/src/test/java/frc4388/utility/RobotTimeUtilityTest.java @@ -1,9 +1,6 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ +// 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 frc4388.utility; @@ -15,90 +12,90 @@ import org.junit.*; * Add your docs here. */ public class RobotTimeUtilityTest { - RobotTime robotTime = RobotTime.getInstance(); + RobotTime robotTime = RobotTime.getInstance(); - @Test - public void testUpdateTimes() { - // Arrange - long lastTime; - robotTime.m_deltaTime = 0; - robotTime.m_robotTime = 0; - robotTime.m_lastRobotTime = 0; - robotTime.m_frameNumber = 0; - robotTime.endMatchTime(); - robotTime.m_lastMatchTime = 0; + @Test + public void testUpdateTimes() { + // Arrange + long lastTime; + robotTime.m_deltaTime = 0; + robotTime.m_robotTime = 0; + robotTime.m_lastRobotTime = 0; + robotTime.m_frameNumber = 0; + robotTime.endMatchTime(); + robotTime.m_lastMatchTime = 0; - // Assert - assertEquals(0, robotTime.m_deltaTime); - assertEquals(0, robotTime.m_robotTime); - assertEquals(0, robotTime.m_lastRobotTime); - assertEquals(0, robotTime.m_frameNumber); - lastTime = robotTime.m_robotTime; + // Assert + assertEquals(0, robotTime.m_deltaTime); + assertEquals(0, robotTime.m_robotTime); + assertEquals(0, robotTime.m_lastRobotTime); + assertEquals(0, robotTime.m_frameNumber); + lastTime = robotTime.m_robotTime; - // Act - wait(1); - robotTime.updateTimes(); + // Act + wait(1); + robotTime.updateTimes(); - // Assert - assertEquals(true, robotTime.m_deltaTime > 0); - assertEquals(true, robotTime.m_robotTime > 0); - assertEquals(lastTime, robotTime.m_lastRobotTime); - assertEquals(1, robotTime.m_frameNumber); - lastTime = robotTime.m_robotTime; + // Assert + assertEquals(true, robotTime.m_deltaTime > 0); + assertEquals(true, robotTime.m_robotTime > 0); + assertEquals(lastTime, robotTime.m_lastRobotTime); + assertEquals(1, robotTime.m_frameNumber); + lastTime = robotTime.m_robotTime; - // Act - wait(1); - robotTime.updateTimes(); + // Act + wait(1); + robotTime.updateTimes(); - // Assert - assertEquals(true, robotTime.m_deltaTime > 0); - assertEquals(true, robotTime.m_robotTime > 0); - assertEquals(lastTime, robotTime.m_lastRobotTime); - assertEquals(2, robotTime.m_frameNumber); - } + // Assert + assertEquals(true, robotTime.m_deltaTime > 0); + assertEquals(true, robotTime.m_robotTime > 0); + assertEquals(lastTime, robotTime.m_lastRobotTime); + assertEquals(2, robotTime.m_frameNumber); + } - @Test - public void testMatchTime() { - // Arrange - long lastTime; + @Test + public void testMatchTime() { + // Arrange + long lastTime; - // Assert - assertEquals(0, robotTime.m_matchTime); - assertEquals(0, robotTime.m_lastMatchTime); - lastTime = robotTime.m_matchTime; + // Assert + assertEquals(0, robotTime.m_matchTime); + assertEquals(0, robotTime.m_lastMatchTime); + lastTime = robotTime.m_matchTime; - // Act - robotTime.startMatchTime(); - wait(1); - robotTime.updateTimes(); + // Act + robotTime.startMatchTime(); + wait(1); + robotTime.updateTimes(); - // Assert - assertEquals(true, robotTime.m_matchTime > 0); - assertEquals(lastTime, robotTime.m_lastMatchTime); - lastTime = robotTime.m_matchTime; - - // Act - wait(1); - robotTime.updateTimes(); - robotTime.endMatchTime(); + // Assert + assertEquals(true, robotTime.m_matchTime > 0); + assertEquals(lastTime, robotTime.m_lastMatchTime); + lastTime = robotTime.m_matchTime; + + // Act + wait(1); + robotTime.updateTimes(); + robotTime.endMatchTime(); - // Assert - assertEquals(0, robotTime.m_matchTime); - assertEquals(lastTime, robotTime.m_lastMatchTime); - lastTime = robotTime.m_matchTime; + // Assert + assertEquals(0, robotTime.m_matchTime); + assertEquals(lastTime, robotTime.m_lastMatchTime); + lastTime = robotTime.m_matchTime; - // Act - wait(1); - robotTime.updateTimes(); + // Act + wait(1); + robotTime.updateTimes(); - // Assert - assertEquals(0, robotTime.m_matchTime); - assertEquals(lastTime, robotTime.m_lastMatchTime); - } + // Assert + assertEquals(0, robotTime.m_matchTime); + assertEquals(lastTime, robotTime.m_lastMatchTime); + } - private void wait(int millis) { - try { - Thread.sleep(millis); - } catch (Exception e) {} - } + private void wait(int millis) { + try { + Thread.sleep(millis); + } catch (Exception e) {} + } } diff --git a/template.config.js b/template.config.js deleted file mode 100644 index 54f2425..0000000 --- a/template.config.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * This file is a configuration file generated by the `Template` extension on `vscode` - * @see https://marketplace.visualstudio.com/items?itemName=yongwoo.template - */ -module.exports = { - // You can change the template path to another path - templateRootPath: "./.templates", - // After copying the template file the `replaceFileTextFn` function is executed - replaceFileTextFn: (fileText, templateName, utils) => { - // @see https://www.npmjs.com/package/change-case - const { changeCase } = utils; - // You can change the text in the file - return fileText - .replace(/__templateName__/gm, templateName) - .replace( - /__templateNameToPascalCase__/gm, - changeCase.pascalCase(templateName) - ) - .replace( - /__templateNameToParamCase__/gm, - changeCase.paramCase(templateName) - ); - }, - replaceFileNameFn: (fileName, templateName, utils) => { - const { path } = utils; - // @see https://nodejs.org/api/path.html#path_path_parse_path - const { base } = path.parse(fileName); - // You can change the file name - return base; - } -}; diff --git a/vendordeps/Phoenix.json b/vendordeps/Phoenix.json index 87f03cb..789d831 100644 --- a/vendordeps/Phoenix.json +++ b/vendordeps/Phoenix.json @@ -1,29 +1,30 @@ { "fileName": "Phoenix.json", "name": "CTRE-Phoenix", - "version": "5.19.4", + "version": "5.20.2", + "frcYear": 2022, "uuid": "ab676553-b602-441f-a38d-f1296eff6537", "mavenUrls": [ - "https://devsite.ctr-electronics.com/maven/release/" + "https://maven.ctr-electronics.com/release/" ], - "jsonUrl": "https://devsite.ctr-electronics.com/maven/release/com/ctre/phoenix/Phoenix-latest.json", + "jsonUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix/Phoenix-frc2022-latest.json", "javaDependencies": [ { "groupId": "com.ctre.phoenix", "artifactId": "api-java", - "version": "5.19.4" + "version": "5.20.2" }, { "groupId": "com.ctre.phoenix", "artifactId": "wpiapi-java", - "version": "5.19.4" + "version": "5.20.2" } ], "jniDependencies": [ { "groupId": "com.ctre.phoenix", "artifactId": "cci", - "version": "5.19.4", + "version": "5.20.2", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -33,7 +34,7 @@ { "groupId": "com.ctre.phoenix.sim", "artifactId": "cci-sim", - "version": "5.19.4", + "version": "5.20.2", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -45,7 +46,19 @@ { "groupId": "com.ctre.phoenix.sim", "artifactId": "simTalonSRX", - "version": "5.19.4", + "version": "5.20.2", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxx86-64" + ] + }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "simTalonFX", + "version": "5.20.2", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -57,7 +70,31 @@ { "groupId": "com.ctre.phoenix.sim", "artifactId": "simVictorSPX", - "version": "5.19.4", + "version": "5.20.2", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxx86-64" + ] + }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "simPigeonIMU", + "version": "5.20.2", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxx86-64" + ] + }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "simCANCoder", + "version": "5.20.2", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -71,52 +108,74 @@ { "groupId": "com.ctre.phoenix", "artifactId": "wpiapi-cpp", - "version": "5.19.4", + "version": "5.20.2", "libName": "CTRE_Phoenix_WPI", "headerClassifier": "headers", - "sharedLibrary": false, + "sharedLibrary": true, "skipInvalidPlatforms": true, "binaryPlatforms": [ - "linuxathena", - "windowsx86-64", - "linuxx86-64", - "osxx86-64" + "linuxathena" ] }, { "groupId": "com.ctre.phoenix", "artifactId": "api-cpp", - "version": "5.19.4", + "version": "5.20.2", "libName": "CTRE_Phoenix", "headerClassifier": "headers", - "sharedLibrary": false, + "sharedLibrary": true, "skipInvalidPlatforms": true, "binaryPlatforms": [ - "linuxathena", - "windowsx86-64", - "linuxx86-64", - "osxx86-64" + "linuxathena" ] }, { "groupId": "com.ctre.phoenix", "artifactId": "cci", - "version": "5.19.4", + "version": "5.20.2", "libName": "CTRE_PhoenixCCI", "headerClassifier": "headers", - "sharedLibrary": false, + "sharedLibrary": true, "skipInvalidPlatforms": true, "binaryPlatforms": [ "linuxathena" ] }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "wpiapi-cpp-sim", + "version": "5.20.2", + "libName": "CTRE_Phoenix_WPISim", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxx86-64" + ] + }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "api-cpp-sim", + "version": "5.20.2", + "libName": "CTRE_PhoenixSim", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxx86-64" + ] + }, { "groupId": "com.ctre.phoenix.sim", "artifactId": "cci-sim", - "version": "5.19.4", + "version": "5.20.2", "libName": "CTRE_PhoenixCCISim", "headerClassifier": "headers", - "sharedLibrary": false, + "sharedLibrary": true, "skipInvalidPlatforms": true, "binaryPlatforms": [ "windowsx86-64", @@ -124,68 +183,10 @@ "osxx86-64" ] }, - { - "groupId": "com.ctre.phoenix", - "artifactId": "diagnostics", - "version": "5.19.4", - "libName": "CTRE_PhoenixDiagnostics", - "headerClassifier": "headers", - "sharedLibrary": false, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "linuxathena", - "windowsx86-64", - "linuxx86-64", - "osxx86-64" - ] - }, - { - "groupId": "com.ctre.phoenix", - "artifactId": "canutils", - "version": "5.19.4", - "libName": "CTRE_PhoenixCanutils", - "headerClassifier": "headers", - "sharedLibrary": false, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxx86-64" - ] - }, - { - "groupId": "com.ctre.phoenix", - "artifactId": "platform-sim", - "version": "5.19.4", - "libName": "CTRE_PhoenixPlatform", - "headerClassifier": "headers", - "sharedLibrary": false, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxx86-64" - ] - }, - { - "groupId": "com.ctre.phoenix", - "artifactId": "core", - "version": "5.19.4", - "libName": "CTRE_PhoenixCore", - "headerClassifier": "headers", - "sharedLibrary": false, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "linuxathena", - "windowsx86-64", - "linuxx86-64", - "osxx86-64" - ] - }, { "groupId": "com.ctre.phoenix.sim", "artifactId": "simTalonSRX", - "version": "5.19.4", + "version": "5.20.2", "libName": "CTRE_SimTalonSRX", "headerClassifier": "headers", "sharedLibrary": true, @@ -196,10 +197,24 @@ "osxx86-64" ] }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "simTalonFX", + "version": "5.20.2", + "libName": "CTRE_SimTalonFX", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxx86-64" + ] + }, { "groupId": "com.ctre.phoenix.sim", "artifactId": "simVictorSPX", - "version": "5.19.4", + "version": "5.20.2", "libName": "CTRE_SimVictorSPX", "headerClassifier": "headers", "sharedLibrary": true, @@ -209,6 +224,34 @@ "linuxx86-64", "osxx86-64" ] + }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "simPigeonIMU", + "version": "5.20.2", + "libName": "CTRE_SimPigeonIMU", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxx86-64" + ] + }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "simCANCoder", + "version": "5.20.2", + "libName": "CTRE_SimCANCoder", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxx86-64" + ] } ] } \ No newline at end of file diff --git a/vendordeps/WPILibNewCommands.json b/vendordeps/WPILibNewCommands.json index 83de291..ab3d1d0 100644 --- a/vendordeps/WPILibNewCommands.json +++ b/vendordeps/WPILibNewCommands.json @@ -34,4 +34,5 @@ ] } ] -} \ No newline at end of file + } + \ No newline at end of file diff --git a/vendordeps/WPILibOldCommands.json b/vendordeps/WPILibOldCommands.json new file mode 100644 index 0000000..acc8879 --- /dev/null +++ b/vendordeps/WPILibOldCommands.json @@ -0,0 +1,37 @@ +{ + "fileName": "WPILibOldCommands.json", + "name": "WPILib-Old-Commands", + "version": "2020.0.0", + "uuid": "b066afc2-5c18-43c4-b758-43381fcb275e", + "mavenUrls": [], + "jsonUrl": "", + "javaDependencies": [ + { + "groupId": "edu.wpi.first.wpilibOldCommands", + "artifactId": "wpilibOldCommands-java", + "version": "wpilib" + } + ], + "jniDependencies": [], + "cppDependencies": [ + { + "groupId": "edu.wpi.first.wpilibOldCommands", + "artifactId": "wpilibOldCommands-cpp", + "version": "wpilib", + "libName": "wpilibOldCommands", + "headerClassifier": "headers", + "sourcesClassifier": "sources", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena", + "linuxraspbian", + "linuxaarch64bionic", + "windowsx86-64", + "windowsx86", + "linuxx86-64", + "osxx86-64" + ] + } + ] +} \ No newline at end of file diff --git a/vendordeps/navx_frc.json b/vendordeps/navx_frc.json index dca1d82..0fb49a7 100644 --- a/vendordeps/navx_frc.json +++ b/vendordeps/navx_frc.json @@ -1,17 +1,17 @@ { "fileName": "navx_frc.json", "name": "KauaiLabs_navX_FRC", - "version": "3.1.413", + "version": "4.0.442", "uuid": "cb311d09-36e9-4143-a032-55bb2b94443b", "mavenUrls": [ "https://repo1.maven.org/maven2/" ], - "jsonUrl": "https://www.kauailabs.com/dist/frc/2020/navx_frc.json", + "jsonUrl": "https://www.kauailabs.com/dist/frc/2022/navx_frc.json", "javaDependencies": [ { "groupId": "com.kauailabs.navx.frc", "artifactId": "navx-java", - "version": "3.1.413" + "version": "4.0.442" } ], "jniDependencies": [], @@ -19,7 +19,7 @@ { "groupId": "com.kauailabs.navx.frc", "artifactId": "navx-cpp", - "version": "3.1.413", + "version": "4.0.442", "headerClassifier": "headers", "sourcesClassifier": "sources", "sharedLibrary": false,