diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..30f4bc5 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,6 @@ +*.gradle text eol=lf +*.java text eol=lf +*.md text eol=lf +*.xml text eol=lf +*.json text eol=lf +*.yml text eol=lf \ No newline at end of file diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 0000000..e8d23de --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,31 @@ +name: Builds 🔨 + +on: [push, pull_request] + +jobs: + pre_build: + runs-on: ubuntu-latest + outputs: + should_skip: ${{ steps.skip_check.outputs.should_skip }} + steps: + - id: skip_check + uses: fkirc/skip-duplicate-actions@v5 + + build: + needs: pre_build + if: needs.pre_build.outputs.should_skip != 'true' + + name: gradle + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + distribution: temurin + java-version: 17 + cache: gradle + - name: Build with Gradle + run: ./gradlew build --no-daemon diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89d358c --- /dev/null +++ b/.gitignore @@ -0,0 +1,170 @@ +# This gitignore has been specially created by the WPILib team. +# If you remove items from this file, intellisense might break. + +### C++ ### +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +### Java ### +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/wpilib.code-snippets + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +### Gradle ### +.gradle +/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Cache of project +.gradletasknamecache + +# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 +# gradle/wrapper/gradle-wrapper.properties + +# # VS Code Specific Java Settings +# DO NOT REMOVE .classpath and .project +.classpath +.project +.settings/ +bin/ + +# Simulation GUI and other tools window save file +*-window.json + +*.snap.debug + +# recording of matches +*.mkv + +*.mirror.path \ No newline at end of file diff --git a/.pathplanner/settings.json b/.pathplanner/settings.json new file mode 100644 index 0000000..3903007 --- /dev/null +++ b/.pathplanner/settings.json @@ -0,0 +1,7 @@ +{ + "robotWidth": 0.85, + "robotLength": 0.851, + "holonomicMode": true, + "generateJSON": false, + "generateCSV": false +} \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..78ce3b0 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + "recommendations": [ + "richardwillis.vscode-spotless-gradle", + "wpilibsuite.vscode-wpilib", + "streetsidesoftware.code-spell-checker", + "vscjava.vscode-gradle", + "redhat.java", + "sonarsource.sonarlint-vscode" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..c9f6b46 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,73 @@ +{ + "java.format.enabled": false, + "files.trimTrailingWhitespace": false, + + "spotlessGradle.format.enable": true, + "spotlessGradle.diagnostics.enable": true, + "editor.defaultFormatter": "richardwillis.vscode-spotless-gradle", + "editor.codeActionsOnSave": { + "source.fixAll.spotlessGradle": true + }, + + "java.configuration.updateBuildConfiguration": "automatic", + "java.server.launchMode": "Standard", + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "bin/": true, + "**/.classpath": true, + "**/.project": true, + "**/.settings": 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", + "cSpell.words": [ + "AHRS", + "apriltag", + "cancoder", + "Chebyshev", + "CONTROLPOINT", + "Deadband", + "deadbanded", + "drivebase", + "fkirc", + "gradlew", + "Hardstop", + "Holonomic", + "LEDS", + "Mockito", + "navx", + "Odometry", + "oshi", + "pathfinding", + "pathing", + "PATHPLANNER", + "PHOTONVISION", + "POWERCYCLE", + "repath", + "REPATHS", + "setpoint", + "Setpoints", + "teleop", + "teleoperated", + "temurin", + "TRACKWIDTH" + ], + "deno.enable": true, + "deno.unstable": true +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..568eb17 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,37 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "gradle", + "id": "gradlebuild", + "script": "build", + "description": "Assembles and tests this project.", + "group": "test", + "project": "FRC-2023", + "buildFile": "${workspaceFolder}/build.gradle", + "rootProject": "FRC-2023", + "projectFolder": "${workspaceFolder}", + "workspaceFolder": "${workspaceFolder}", + "args": "", + "javaDebug": false, + "problemMatcher": ["$gradle"], + "label": "gradle: build" + }, + { + "type": "gradle", + "id": "gradledeploy", + "script": "deploy", + "description": "Deploy all artifacts on all targets", + "group": "build", + "project": "FRC-2023", + "buildFile": "${workspaceFolder}/build.gradle", + "rootProject": "FRC-2023", + "projectFolder": "${workspaceFolder}", + "workspaceFolder": "${workspaceFolder}", + "args": "", + "javaDebug": false, + "problemMatcher": ["$gradle"], + "label": "gradle: deploy" + } + ] +} diff --git a/.vscode/wpilib.code-snippets b/.vscode/wpilib.code-snippets new file mode 100644 index 0000000..d78840a --- /dev/null +++ b/.vscode/wpilib.code-snippets @@ -0,0 +1,50 @@ +{ + // Place your FRC-2023 workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and + // description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope + // is left empty or omitted, the snippet gets applied to all languages. The prefix is what is + // used to trigger the snippet and the body will be expanded and inserted. Possible variables are: + // $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. + // Placeholders with the same ids are connected. + // Example: + // "Print to console": { + // "scope": "javascript,typescript", + // "prefix": "log", + // "body": [ + // "console.log('$1');", + // "$2" + // ], + // "description": "Log output to console" + // } + "Constants Block": { + "scope": "java", + "prefix": "block", + "body": ["public static final class $1 {$0}"] + }, + "Constant": { + "scope": "java", + "prefix": "const", + "body": ["public static final ${1:int} ${2/(.*)/${1:/upcase}/} = ${3:0};$0"] + }, + "This Member": { + "scope": "java", + "prefix": "thisprop", + "body": ["this.$1 = $1;$0"] + }, + "TalonFX percent power": { + "scope": "java", + "prefix": "fxper", + "body": ["$1.set(TalonFXControlMode.PercentOutput, $2);$0"] + }, + "New subsystem member for robotcontainer": { + "scope": "java", + "prefix": "newsub", + "body": ["private final $1 $2 = new $1();$0"] + }, + "verify the setting of a talonfx power in a given control mode": { + "scope": "java", + "prefix": "vfxset", + "body": [ + "verify($1, ${2:times(1)}.description(String.format(\"$3\",$4))).set(TalonFXControlMode.${5:PercentOutput}, $6);$0" + ] + } +} diff --git a/.wpilib/wpilib_preferences.json b/.wpilib/wpilib_preferences.json new file mode 100644 index 0000000..7a00ec5 --- /dev/null +++ b/.wpilib/wpilib_preferences.json @@ -0,0 +1,6 @@ +{ + "enableCppIntellisense": false, + "currentLanguage": "java", + "projectYear": "2023", + "teamNumber": 5026 +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..67d6707 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Iron Panthers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README copy.md b/README copy.md new file mode 100644 index 0000000..687e3da --- /dev/null +++ b/README copy.md @@ -0,0 +1,111 @@ +# FRC-2023 + +Iron Panthers repository for 2023 season code. + +## Setting up + +### Before working: make sure you have the 2023 tools: + +- WPILib: download the latest release from [allwpilib](https://github.com/wpilibsuite/allwpilib/releases/latest). Run installer executable. Should include VS Code + extensions + - using provided vscode is easier, but not ideal for everyone - it is optional + - if you want to use your own vscode, just follow steps below to get extension running +- if you want to install VS Code extension separately, or for your own vscode instance + - check if the version in the vscode store is up to date + - if it is, install from there, make life easy + - if not, do the following + - download the latest .vsix release from [vscode-wpilib](https://github.com/wpilibsuite/vscode-wpilib/releases/latest) + - open vscode + - trigger command, which is ``ctrl shift p`` on linux + - type install from and select vsix + - select the vsix you downloaded +- Node.js: download 16 lts (or newer if you want / already have) from [node.js](https://nodejs.org/en/) + - we use node for spotless linting on a few files with prettier + - if node is not installed the build will fail + - on windows, ***you will need to reboot for this to work*** + - on linux, install from your package manager + +### Run a test build + +Open command pallette (``ctrl shift p`` on linux) and type "build robot code" until you see the command. Running this command will build ***but not deploy*** your robot code, so you can check for syntax, linting, and library issues, among other things. If this says ``BUILD SUCCESSFUL`` it means all is working. + +### Install additional recommended extensions + +You should install a few vscode extensions to make our lives easier. + +- Spotless Gradle + - this will let you see linting errors in the editor + - this will also automatically format your code to conform to linting rules +- Code Spell Checker (cSpell) + - this will highlight likely typos + - if you see something highlighted as a typo when it shouldn't be, like a robotics term, use the code action to ``Add: "xxx" to workspace settings`` so we all can benefit + +## Getting work done + +### Building to test code + +If you want to build code and run tests, the build robot code command will do that. However, the vscode test task is also configured to do this, so running that with the keybinding you set will have the same effect. + +To configure keybindings for testing and deploying, open the command pallette and run open keyboard shortcuts. Search ``tasks: run build`` to see build, and ``tasks: run test`` to see test. I configured my test task to be ``ctrl shift b ctrl shift j`` and my build task to be ``ctrl shift b ctrl shift b``. Vscode keybindings support chording, so you can put many things as the second layer of a binding. + +### Deploying code + +1. Turn on the robot +1. Wait for the radio light to be orange, letting you know wifi is on +1. Connect to robot wifi, probably named ``5026_(charles|devil|rat)`` with a name hopefully written on the radio (small white box) +1. Trigger the deploy action, either with command pallette or task keybinding +1. Connect the the network with a computer running driver station - it's only supported on windows, so if you want to deploy from your mac / linux device, use a driverstation in addition +1. Ensure the robot couldn't break things if it moved quickly / flung arm ect +1. Ask people near the robot if it is ok to enable if they are unaware of your plans +1. Say "Enabling!" loud enough everyone nearby can here you ***and wait for people to get away from the robot*** (very important) +1. Wait for someone to say "Clear" confirming that everyone is clear of the robot +1. Use the enable button on the driverstation to enable the robot +1. Ensure you or someone who understands the following is always close enough to the driverstation to stop the robot +1. Use the disable button to stop it when your done testing, or if the robot endangers itself / property / people because of your code +1. If something bad is happening, hit the enter to disable robot - you don't even need to have the driverstation focused. Don't bother looking for the disable button if someone is dying. +1. If something really bad is happening, hit the spacebar to disable robot and delete your code. This will require you to redeploy before the robot does anything again + +### Writing code + +When writing code, there are a few rules + changes to know. + +- We have decided to stop using ``m_`` prefix for members of an object +- Constant blocks in ``Constants.java`` are PascalCase +- Constant variables in ``Constants.java`` are SCREAMING_SNAKE_CASE +- All subsystem filenames should be suffixed with Subsystem + - ``ExampleSubsystem.java`` +- All command filenames should be suffixed with Command + - ``ExampleCommand.java`` +- Controllers are named after the driver who uses them, ``jason`` and ``will`` + +### Code snippets + +Code snippets are a vscode feature to allow easy typing of repetitive things. If snippets are added, they should be noted here - see ``.vscode/wpilib.code-snippets`` for examples if you want to write more. The prefix of a snippet is what you type to trigger it. To move between the places to fill in, use ``tab``. + +| prefix | code | +| --- | --- | +| ``block`` | ``public static final class name {}`` | +| ``const`` | ``public static final type name = val;`` | +| ``thisprop`` | ``this.name = name;`` | +| ``fxper`` | ``motor.set(TalonFXControlMode.PercentOutput, percent);`` | +| ``newsub`` | ``private final SubsystemClassPascalCase subsystemClassCamelCase = new SubsystemClass();`` | +| ``vfxset`` | ``verify(motor, times(1).description(String.format("uh oh, %s", obj))).set(TalonFXControlMode.mode, value);`` | + +### Collaborating on Code + +To collaborate on code, keep a few things in mind: + +- keep your feature branch fresh + - this means merge dev into your branch when things are changed on dev + - the worst case is that it takes a bit of time, but keeping your branch fresh will prevent large and difficult merge conflicts, because you will solve it as it happens +- unblock fast and seek collaboration + - when you get stuck on something, "blocked", you should get unblocked quickly + - while you could probably solve the issue yourself, you are surrounded by people with different experiences who may have already solved something similar + - even if nobody knows the issue right away, summarizing the problem is usually a path to solution - looking at it in a new light +- critique code, not people + - be kind to whoever wrote the code you take issue with + - talk in terms of code, not who wrote it + - "the code is crashing" vs "you crashed the robot" + - similarly, don't be defensive about your code - you aren't your code + - we should be mean to code, but not to people + +If you pick up tips and tricks as you learn, make a pr and add them to the readme. 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 new file mode 100644 index 0000000..a4506c2 --- /dev/null +++ b/build.gradle @@ -0,0 +1,202 @@ +plugins { + id "java" + id "edu.wpi.first.GradleRIO" version "2023.4.2" + id "com.diffplug.spotless" version "6.13.0" + id "me.champeau.jmh" version "0.6.8" +} + +sourceCompatibility = JavaVersion.VERSION_17 +targetCompatibility = JavaVersion.VERSION_17 + +def ROBOT_MAIN_CLASS = "frc.robot.Main" + +// Define my targets (RoboRIO) and artifacts (deployable files) +// This is added by GradleRIO's backing project DeployUtils. +deploy { + targets { + roborio(getTargetTypeClass('RoboRIO')) { + // Team number is loaded either from the .wpilib/wpilib_preferences.json + // or from command line. If not found an exception will be thrown. + // You can use getTeamOrDefault(team) instead of getTeamNumber if you + // want to store a team number in this file. + team = project.frc.getTeamNumber() + debug = project.frc.getDebugOrDefault(false) + + artifacts { + // First part is artifact name, 2nd is artifact type + // getTargetTypeClass is a shortcut to get the class type using a string + + frcJava(getArtifactTypeClass('FRCJavaArtifact')) { + } + + // Static files artifact + frcStaticFileDeploy(getArtifactTypeClass('FileTreeArtifact')) { + files = project.fileTree('src/main/deploy') + directory = '/home/lvuser/deploy' + } + } + } + } +} + +def deployArtifact = deploy.targets.roborio.artifacts.frcJava + +// Set to true to use debug for JNI. +wpi.java.debugJni = false + +// Set this to true to enable desktop support. +def includeDesktopSupport = false + +// Defining my dependencies. In this case, WPILib (+ friends), and vendor libraries. +// Also defines JUnit 5. +dependencies { + implementation wpi.java.deps.wpilib() + implementation wpi.java.vendor.java() + + // lets us read system uptime data + implementation group: 'com.github.oshi', name: 'oshi-core', version: '6.3.1' + + roborioDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.roborio) + roborioDebug wpi.java.vendor.jniDebug(wpi.platforms.roborio) + + roborioRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.roborio) + roborioRelease wpi.java.vendor.jniRelease(wpi.platforms.roborio) + + nativeDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.desktop) + nativeDebug wpi.java.vendor.jniDebug(wpi.platforms.desktop) + simulationDebug wpi.sim.enableDebug() + + nativeRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.desktop) + nativeRelease wpi.java.vendor.jniRelease(wpi.platforms.desktop) + simulationRelease wpi.sim.enableRelease() + + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2' + testImplementation 'org.junit.jupiter:junit-jupiter-params:5.8.2' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2' + + testImplementation "org.mockito:mockito-core:3.+" + testImplementation "org.mockito:mockito-inline:3.+" + testImplementation 'org.mockito:mockito-junit-jupiter:4.3.1' + + // profiling! + testImplementation 'org.openjdk.jmh:jmh-core:1.19' + testImplementation 'org.openjdk.jmh:jmh-generator-annprocess:1.19' + + // snapshot testing! + testImplementation 'io.github.origin-energy:java-snapshot-testing-junit5:4.+' + + // java-snapshot-testing json serialization + testImplementation 'io.github.origin-energy:java-snapshot-testing-plugin-jackson:4.+' + testImplementation 'com.fasterxml.jackson.core:jackson-core:2.11.3' + testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.11.3' + + // java-snapshot-testing optional support + testRuntimeOnly 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.11.3' + testRuntimeOnly 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.11.3' + + // logger! + testImplementation 'org.slf4j:slf4j-simple:2.0.6' +} + +// Simulation configuration (e.g. environment variables). +wpi.sim.addGui().defaultEnabled = true +wpi.sim.addDriverstation() + +// Setting up my Jar File. In this case, adding all libraries into the main jar ('fat jar') +// in order to make them all available at runtime. Also adding the manifest so WPILib +// knows where to look for our Robot Class. +jar { + from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } + manifest edu.wpi.first.gradlerio.GradleRIOPlugin.javaManifest(ROBOT_MAIN_CLASS) + duplicatesStrategy = DuplicatesStrategy.INCLUDE +} + +// configure tests +test { + useJUnitPlatform() + + systemProperty 'java.util.logging.config.file', "${project.projectDir}/src/test/resources/logging-test.properties" + + systemProperty 'junit.jupiter.extensions.autodetection.enabled', 'true' + + testLogging { + showStandardStreams = true; + exceptionFormat = 'full' // show expected and actual for failed tests + } +} + +jmh { + warmupIterations = 2 + iterations = 5 + fork = 1 +} + +tasks.create("bmPathfinding") { + jmh.includes.add("GraphPathfinderBenchmarks.findOptimalPath") + finalizedBy("jmh") +} + +// Configure jar and deploy tasks +deployArtifact.jarTask = jar +wpi.java.configureExecutableTasks(jar) +wpi.java.configureTestTasks(test) + +spotless { + java { + target fileTree('.') { + include '**/*.java' + exclude '**/build/**', '**/build-*/**' + } + toggleOffOn() + googleJavaFormat() + removeUnusedImports() + trimTrailingWhitespace() + endWithNewline() + } + groovyGradle { + target fileTree('.') { + include '**/*.gradle' + exclude '**/build/**', '**/build-*/**' + } + greclipse() + indentWithSpaces(4) + trimTrailingWhitespace() + endWithNewline() + } + format 'xml', { + target fileTree('.') { + include '**/*.xml' + exclude '**/build/**', '**/build-*/**' + } + eclipseWtp('xml') + trimTrailingWhitespace() + indentWithSpaces(2) + endWithNewline() + } + format "styling", { + target fileTree(".vscode") { + include "**.json" + }, + fileTree(".wpilib") { + include "**.json" + }, + fileTree(".github") { + include "**/*.yml" + } + // prettier("2.5.1") + } + format 'misc', { + target fileTree('.') { + include '**/*.md', '**/.gitignore' + exclude '**/build/**', '**/build-*/**' + } + trimTrailingWhitespace() + indentWithSpaces(2) + endWithNewline() + } +} + +// Configure string concat to always inline compile +tasks.withType(JavaCompile) { + options.compilerArgs.add '-XDstringConcat=inline' +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..249e583 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..c23a1b3 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=permwrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=permwrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..837b038 --- /dev/null +++ b/gradlew @@ -0,0 +1,240 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +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 + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + 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 +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +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 + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# 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 \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..f127cfd --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,91 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..48c039e --- /dev/null +++ b/settings.gradle @@ -0,0 +1,27 @@ +import org.gradle.internal.os.OperatingSystem + +pluginManagement { + repositories { + mavenLocal() + gradlePluginPortal() + String frcYear = '2023' + File frcHome + if (OperatingSystem.current().isWindows()) { + String publicFolder = System.getenv('PUBLIC') + if (publicFolder == null) { + publicFolder = "C:\\Users\\Public" + } + def homeRoot = new File(publicFolder, "wpilib") + frcHome = new File(homeRoot, frcYear) + } else { + def userFolder = System.getProperty("user.home") + def homeRoot = new File(userFolder, "wpilib") + frcHome = new File(homeRoot, frcYear) + } + def frcHomeMaven = new File(frcHome, 'maven') + maven { + name 'frcHome' + url frcHomeMaven + } + } +} diff --git a/src/main/deploy/example.txt b/src/main/deploy/example.txt new file mode 100644 index 0000000..bb82515 --- /dev/null +++ b/src/main/deploy/example.txt @@ -0,0 +1,3 @@ +Files placed in this directory will be deployed to the RoboRIO into the +'deploy' directory in the home folder. Use the 'Filesystem.getDeployDirectory' wpilib function +to get a proper path relative to the deploy directory. \ No newline at end of file diff --git a/src/main/java/frc/robot/Constants.java b/src/main/java/frc/robot/Constants.java new file mode 100644 index 0000000..915ef9c --- /dev/null +++ b/src/main/java/frc/robot/Constants.java @@ -0,0 +1,17 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot; + +@SuppressWarnings("java:S1118") +/** + * The Constants class provides a convenient place for teams to hold robot-wide numerical or boolean + * constants. This class should not be used for any other purpose. All constants should be declared + * globally (i.e. public static). Do not put anything functional in this class. + * + *

It is advised to statically import this class (or one of its inner classes) wherever the + * constants are needed, to reduce verbosity. + */ +public final class Constants { +} diff --git a/src/main/java/frc/robot/Main.java b/src/main/java/frc/robot/Main.java new file mode 100644 index 0000000..8776e5d --- /dev/null +++ b/src/main/java/frc/robot/Main.java @@ -0,0 +1,25 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot; + +import edu.wpi.first.wpilibj.RobotBase; + +/** + * Do NOT add any static variables to this class, or any initialization at all. Unless you know what + * you are doing, do not modify this file except to change the parameter class to the startRobot + * call. + */ +public final class Main { + private Main() {} + + /** + * Main initialization function. Do not perform any initialization here. + * + *

If you change your main robot class, change the parameter type. + */ + public static void main(String... args) { + RobotBase.startRobot(Robot::new); + } +} diff --git a/src/main/java/frc/robot/Robot.java b/src/main/java/frc/robot/Robot.java new file mode 100644 index 0000000..9aaf8a9 --- /dev/null +++ b/src/main/java/frc/robot/Robot.java @@ -0,0 +1,95 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot; + +import edu.wpi.first.wpilibj.TimedRobot; +import edu.wpi.first.wpilibj.livewindow.LiveWindow; +import edu.wpi.first.wpilibj2.command.CommandScheduler; + +/** + * The VM is configured to automatically run this class, and to call the functions corresponding to + * each mode, as described in the TimedRobot documentation. If you change the name of this class or + * the package after creating this project, you must also update the build.gradle file in the + * project. + */ +public class Robot extends TimedRobot { + + private RobotContainer robotContainer; + + /** + * This function is run when the robot is first started up and should be used for any + * initialization code. + */ + @Override + public void robotInit() { + // Instantiate our RobotContainer. This will perform all our button bindings, and put our + // autonomous chooser on the dashboard. + robotContainer = new RobotContainer(); + + LiveWindow.disableAllTelemetry(); + } + + /** + * This function is called every robot packet, no matter the mode. Use this for items like + * diagnostics that you want ran during disabled, autonomous, teleoperated and test. + * + *

This runs after the mode specific periodic functions, but before LiveWindow and + * SmartDashboard integrated updating. + */ + @Override + public void robotPeriodic() { + // Runs the Scheduler. This is responsible for polling buttons, adding newly-scheduled + // commands, running already-scheduled commands, removing finished or interrupted commands, + // and running subsystem periodic() methods. This must be called from the robot's periodic + // block in order for anything in the Command-based framework to work. + CommandScheduler.getInstance().run(); + } + + /** This function is called once each time the robot enters Disabled mode. */ + @Override + public void disabledInit() { + // This method intentionally left empty + } + + @Override + public void disabledPeriodic() { + // This method intentionally left empty + } + + /** This autonomous runs the autonomous command selected by your {@link RobotContainer} class. */ + @Override + public void autonomousInit() { + } + + /** This function is called periodically during autonomous. */ + @Override + public void autonomousPeriodic() { + // This method intentionally left empty + } + + @Override + public void teleopInit() { + // do stuff like vibration of controllers at match start + robotContainer.containerTeleopInit(); + } + + /** This function is called periodically during operator control. */ + @Override + public void teleopPeriodic() { + // This method intentionally left empty + } + + @Override + public void testInit() { + // Cancels all running commands at the start of test mode. + CommandScheduler.getInstance().cancelAll(); + } + + /** This function is called periodically during test mode. */ + @Override + public void testPeriodic() { + // This method intentionally left empty + } +} diff --git a/src/main/java/frc/robot/RobotContainer.java b/src/main/java/frc/robot/RobotContainer.java new file mode 100644 index 0000000..0d3b8e4 --- /dev/null +++ b/src/main/java/frc/robot/RobotContainer.java @@ -0,0 +1,54 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.robot; + +/** + * This class is where the bulk of the robot should be declared. Since Command-based is a + * "declarative" paradigm, very little robot logic should actually be handled in the {@link Robot} + * periodic methods (other than the scheduler calls). Instead, the structure of the robot (including + * subsystems, commands, and button mappings) should be declared here. + */ +public class RobotContainer { + // The robot's subsystems and commands are defined here... + + /** The container for the robot. Contains subsystems, OI devices, and commands. */ + public RobotContainer() { + // Configure the button bindings + configureButtonBindings(); + } + + /** + * Use this method to do things as the drivers gain control of the robot. We use it to vibrate the + * driver b controller to notice accidental swaps. + * + *

Please use this very, very sparingly. It doesn't exist by default for good reason. + */ + public void containerTeleopInit() { + // runs when teleop happens + } + + /** + * Use this method to do things as soon as the robot starts being used. We use it to stop doing + * things that could be harmful or undesirable during game play--rebooting the network switch is a + * good example. Subsystems need to be explicitly wired up to this method. + * + *

Depending on which mode the robot is enabled in, this will either be called before auto or + * before teleop, whichever is first. + * + *

Please use this very, very sparingly. It doesn't exist by default for good reason. + */ + public void containerMatchStarting() { + // runs when the match starts + } + + /** + * 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() { + } +} diff --git a/src/main/java/frc/util/ControllerUtil.java b/src/main/java/frc/util/ControllerUtil.java new file mode 100644 index 0000000..dbf30ed --- /dev/null +++ b/src/main/java/frc/util/ControllerUtil.java @@ -0,0 +1,40 @@ +package frc.util; + +import java.util.function.BooleanSupplier; + +public class ControllerUtil { + /** + * Scales radial deadband + * + *

The deadband value is set to be the new zero + * + * @param value the raw value + * @param deadband the deadband range + * @return the value with radial deadband applied + */ + public static double deadband(double value, double deadband) { + if (Math.abs(value) > deadband) { + if (value > 0.0) { + return (value - deadband) / (1.0 - deadband); + } else { + return (value + deadband) / (1.0 - deadband); + } + } else { + return 0.0; + } + } + + private ControllerUtil() {} + /** + * Compares a layer button with a layer state, and if they match returns the layered button + * + * @param layer the boolean supplier that is the layer switch + * @param layerState the state of the layer switch that is valid + * @param button the button inside the layer + * @return true if the layer is enabled and the button is pressed + */ + public static BooleanSupplier cumBooleanSupplier( + BooleanSupplier layer, boolean layerState, BooleanSupplier button) { + return () -> layer.getAsBoolean() == layerState && button.getAsBoolean(); + } +} diff --git a/src/main/java/frc/util/Layer.java b/src/main/java/frc/util/Layer.java new file mode 100644 index 0000000..1256cb0 --- /dev/null +++ b/src/main/java/frc/util/Layer.java @@ -0,0 +1,154 @@ +package frc.util; + +import edu.wpi.first.util.function.BooleanConsumer; +import edu.wpi.first.wpilibj.event.EventLoop; +import edu.wpi.first.wpilibj2.command.CommandScheduler; +import edu.wpi.first.wpilibj2.command.InstantCommand; +import edu.wpi.first.wpilibj2.command.button.Trigger; +import java.util.function.BooleanSupplier; + +/** + * An object to use a {@link Trigger} or {@link Trigger} as a layerSwitch to form two layers of + * virtual Triggers, with the switch on or off + */ +public class Layer { + /** + * the trigger that is used for on and off states for the layer such that the states correspond to + * the state of the trigger + */ + private final Trigger layerSwitch; + + private final EventLoop eventLoop; + + /** + * Constructs a new Layer based off of an arbitrary boolean supplier. + * + * @param layerSwitch BooleanSupplier representing the layer root. + */ + public Layer(BooleanSupplier layerSwitch) { + this(new Trigger(layerSwitch)); + } + + /** + * Constructs a new Layer based off of a {@link Trigger}. + * + * @param layerSwitch WPILib Trigger representing the layer root. + */ + public Layer(Trigger layerSwitch) { + this(CommandScheduler.getInstance().getDefaultButtonLoop(), layerSwitch); + } + + public Layer(EventLoop eventLoop, Trigger layerSwitch) { + this.eventLoop = eventLoop; + this.layerSwitch = layerSwitch; + } + + /** + * gets the Trigger that controls the layering + * + * @return + */ + public Trigger getLayerSwitch() { + return layerSwitch; + } + + public void whenChanged(BooleanConsumer method) { + Trigger layerTrigger = new Trigger(eventLoop, this.layerSwitch); + layerTrigger.onTrue( + new InstantCommand( + () -> { + method.accept(true); + })); + layerTrigger.onFalse( + new InstantCommand( + () -> { + method.accept(false); + })); + } + + private static class BooleanRef { + boolean val; + + public BooleanRef(boolean val) { + this.val = val; + } + } + + /** + * Combines a {@link Trigger} with the layer switch to form a virtual trigger that is only true + * when the layer switch is true and the trigger is true. + * + * @param trigger the {@link Trigger} that is used in tandem with the layer for the virtual + * Trigger + * @return virtual {@link Trigger} that is pressed when the layer switch and the provided Trigger + * is pressed + */ + public Trigger on(Trigger trigger) { + return new Trigger(eventLoop, layerSwitch.and(trigger)); + } + + /** + * Combines a {@link BooleanSupplier} with the layer switch to form a virtual trigger that is only + * true when the layer switch is true and the trigger is true. + * + * @param Trigger the {@link BooleanSupplier} that is used in tandem with the layer for the + * virtual Trigger + * @return virtual {@link Trigger} that is pressed when the layer switch and the provided Trigger + * is pressed + */ + public Trigger on(BooleanSupplier boolSupplier) { + return on(new Trigger(eventLoop, boolSupplier)); + } + + /** + * Combines a {@link Trigger} with the layer switch to form a virtual trigger that is only true + * when the layer switch is false and the trigger is true. Additionally, the virtual trigger will + * be false if the layer switch was released but the trigger was still pressed, until the trigger + * is released. + * + * @param trigger the {@link Trigger} that is used in tandem with the layer for the virtual + * Trigger + * @return virtual {@link Trigger} that is pressed when the layer switch is not pressed, but the + * provided Trigger is pressed + */ + public Trigger off(Trigger trigger) { + final BooleanRef layerSwitchWasTrue = new BooleanRef(false); + return new Trigger( + eventLoop, + () -> { + final boolean layerSwitchVal = layerSwitch.getAsBoolean(); + final boolean triggerVal = trigger.getAsBoolean(); + + if (layerSwitchVal) { + layerSwitchWasTrue.val = true; + return false; + } + + if (!layerSwitchVal && !triggerVal) { + layerSwitchWasTrue.val = false; + return false; + } + + if (layerSwitchWasTrue.val) { + return false; + } + + return !layerSwitchVal && triggerVal; + }); + } + + /** + * Combines a {@link BooleanSupplier} with the layer switch to form a virtual trigger that is only + * true when the layer switch is false and the trigger is true. Additionally, the virtual trigger + * will be false if the layer switch was released but the trigger was still pressed, until the + * trigger is released. + * + * @param Trigger the {@link BooleanSupplier} that is used in tandem with the layer for the + * virtual Trigger + * @return virtual {@link Trigger} that is pressed when the layer switch is not pressed, but the + * provided Trigger is pressed + */ + public Trigger off(BooleanSupplier boolSupplier) { + return off(new Trigger(eventLoop, boolSupplier)); + } +} diff --git a/src/main/java/frc/util/SmartBoard.java b/src/main/java/frc/util/SmartBoard.java new file mode 100644 index 0000000..7d7c9a8 --- /dev/null +++ b/src/main/java/frc/util/SmartBoard.java @@ -0,0 +1,40 @@ +package frc.util; + +import edu.wpi.first.networktables.GenericEntry; +import edu.wpi.first.wpilibj.shuffleboard.BuiltInWidgets; +import edu.wpi.first.wpilibj.shuffleboard.ShuffleboardTab; +import java.util.Map; +import java.util.function.DoubleConsumer; +import java.util.function.DoubleSupplier; + +public class SmartBoard { + + public record Range(double min, double max) { + private Map asConfig() { + return Map.of("min", min, "max", max); + } + } + + private GenericEntry entry; + private DoubleSupplier supplier; + private DoubleConsumer consumer; + + public SmartBoard( + ShuffleboardTab tab, + String name, + DoubleSupplier supplier, + DoubleConsumer consumer, + Range range) { + this.supplier = supplier; + this.consumer = consumer; + entry = + tab.add(name, supplier.getAsDouble()) + .withWidget(BuiltInWidgets.kNumberSlider) + .withProperties(range.asConfig()) + .getEntry(); + } + + public void poll() { + consumer.accept(entry.getDouble(supplier.getAsDouble())); + } +} diff --git a/src/main/java/frc/util/Util.java b/src/main/java/frc/util/Util.java new file mode 100644 index 0000000..0a41be0 --- /dev/null +++ b/src/main/java/frc/util/Util.java @@ -0,0 +1,126 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package frc.util; + +import edu.wpi.first.math.geometry.Rotation2d; +import edu.wpi.first.math.geometry.Translation2d; +import edu.wpi.first.math.kinematics.ChassisSpeeds; + +public class Util { + private Util() {} + + public static boolean epsilonEquals(double a, double b, double epsilon) { + return (a - epsilon <= b) && (a + epsilon >= b); + } + + public static boolean epsilonZero(double a, double epsilon) { + return epsilonEquals(a, 0, epsilon); + } + + /** + * Modulo on a negative number returns a negative number. This function always returns positive + * numbers, even for negative angles, without rotation. + * + * @param degrees + * @return normalized degrees + */ + public static double normalizeDegrees(double degrees) { + return (degrees % 360 + 360) % 360; + } + + /** + * This function finds the degree difference between angles, the shortest path. Useful for pid + * control of drivebase rotation. Returns a value between -180 and 180 on a 360 reference field. + * Values greater than 180 won't exist, because the other direction is shorter. + * + * @param currentAngle Current Angle Degrees + * @param newAngle Target Angle Degrees + * @return Shortest angular difference in degrees + */ + public static double relativeAngularDifference(double currentAngle, double newAngle) { + double a = normalizeDegrees(currentAngle - newAngle); + double b = normalizeDegrees(newAngle - currentAngle); + return a < b ? a : -b; + } + + public static double relativeAngularDifference(Rotation2d currentAngle, double newAngle) { + return relativeAngularDifference(currentAngle.getDegrees(), newAngle); + } + + public static double relativeAngularDifference(Rotation2d currentAngle, Rotation2d newAngle) { + return relativeAngularDifference(currentAngle.getDegrees(), newAngle.getDegrees()); + } + + /** + * turn x and y of a vector to a [0, 360] angle + * + * @param x x value of vector + * @param y y value of vector + * @return [0, 360] mapped angle of vector + */ + public static double vectorToAngle(double x, double y) { + double angle = Math.atan2(y, x); + return (angle * (180 / Math.PI) + 360) % 360; + } + + /** + * snap an angle to the closest angle in an array of angles + * + * @param angle angle to be snapped + * @param snaps array of angles to snap to + * @return closest angle in snap array + */ + public static double angleSnap(double angle, double[] snaps) { + double closest = snaps[0]; + for (double snap : snaps) { + if (Math.abs(relativeAngularDifference(angle, snap)) + < Math.abs(relativeAngularDifference(angle, closest))) { + closest = snap; + } + } + return closest; + } + + public static double vectorMagnitude(double x, double y) { + return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); + } + + public static double getVelocity(ChassisSpeeds chassisSpeeds) { + return Math.sqrt( + Math.pow(chassisSpeeds.vxMetersPerSecond, 2) + + Math.pow(chassisSpeeds.vyMetersPerSecond, 2)); + } + + /** + * Solve for the translation velocity of a robot given its frame relative chassis speeds and + * heading. Does the opposite of {@link ChassisSpeeds#fromFieldRelativeSpeeds}. + * + * @param chassisSpeeds + * @param robotAngle + * @return + */ + public static Translation2d getTranslationVelocity( + ChassisSpeeds chassisSpeeds, Rotation2d robotAngle) { + // the from field relative speeds impl + /* + public static ChassisSpeeds fromFieldRelativeSpeeds( + double vxMetersPerSecond, + double vyMetersPerSecond, + double omegaRadiansPerSecond, + Rotation2d robotAngle) { + return new ChassisSpeeds( + vxMetersPerSecond * robotAngle.getCos() + vyMetersPerSecond * robotAngle.getSin(), + -vxMetersPerSecond * robotAngle.getSin() + vyMetersPerSecond * robotAngle.getCos(), + omegaRadiansPerSecond); + } + */ + + return new Translation2d( + chassisSpeeds.vxMetersPerSecond * robotAngle.getCos() + - chassisSpeeds.vyMetersPerSecond * robotAngle.getSin(), + chassisSpeeds.vxMetersPerSecond * robotAngle.getSin() + + chassisSpeeds.vyMetersPerSecond * robotAngle.getCos()); + } +} diff --git a/vendordeps/NavX.json b/vendordeps/NavX.json new file mode 100644 index 0000000..29ec93a --- /dev/null +++ b/vendordeps/NavX.json @@ -0,0 +1,39 @@ +{ + "fileName": "NavX.json", + "name": "KauaiLabs_navX_FRC", + "version": "2023.0.3", + "uuid": "cb311d09-36e9-4143-a032-55bb2b94443b", + "mavenUrls": [ + "https://dev.studica.com/maven/release/2023/" + ], + "jsonUrl": "https://dev.studica.com/releases/2023/NavX.json", + "javaDependencies": [ + { + "groupId": "com.kauailabs.navx.frc", + "artifactId": "navx-frc-java", + "version": "2023.0.3" + } + ], + "jniDependencies": [], + "cppDependencies": [ + { + "groupId": "com.kauailabs.navx.frc", + "artifactId": "navx-frc-cpp", + "version": "2023.0.3", + "headerClassifier": "headers", + "sourcesClassifier": "sources", + "sharedLibrary": false, + "libName": "navx_frc", + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena", + "linuxraspbian", + "linuxarm32", + "linuxarm64", + "linux86-64", + "osxuniversal", + "windowsx86-64" + ] + } + ] +} \ No newline at end of file diff --git a/vendordeps/PathplannerLib.json b/vendordeps/PathplannerLib.json new file mode 100644 index 0000000..69fddcd --- /dev/null +++ b/vendordeps/PathplannerLib.json @@ -0,0 +1,35 @@ +{ + "fileName": "PathplannerLib.json", + "name": "PathplannerLib", + "version": "2023.4.3", + "uuid": "1b42324f-17c6-4875-8e77-1c312bc8c786", + "mavenUrls": [ + "https://3015rangerrobotics.github.io/pathplannerlib/repo" + ], + "jsonUrl": "https://3015rangerrobotics.github.io/pathplannerlib/PathplannerLib.json", + "javaDependencies": [ + { + "groupId": "com.pathplanner.lib", + "artifactId": "PathplannerLib-java", + "version": "2023.4.3" + } + ], + "jniDependencies": [], + "cppDependencies": [ + { + "groupId": "com.pathplanner.lib", + "artifactId": "PathplannerLib-cpp", + "version": "2023.4.3", + "libName": "PathplannerLib", + "headerClassifier": "headers", + "sharedLibrary": false, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal", + "linuxathena" + ] + } + ] +} \ No newline at end of file diff --git a/vendordeps/Phoenix.json b/vendordeps/Phoenix.json new file mode 100644 index 0000000..27ee06e --- /dev/null +++ b/vendordeps/Phoenix.json @@ -0,0 +1,423 @@ +{ + "fileName": "Phoenix.json", + "name": "CTRE-Phoenix (v5)", + "version": "5.30.4+23.0.8", + "frcYear": 2023, + "uuid": "ab676553-b602-441f-a38d-f1296eff6537", + "mavenUrls": [ + "https://maven.ctr-electronics.com/release/" + ], + "jsonUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix/Phoenix5-frc2023-latest.json", + "javaDependencies": [ + { + "groupId": "com.ctre.phoenix", + "artifactId": "api-java", + "version": "5.30.4" + }, + { + "groupId": "com.ctre.phoenix", + "artifactId": "wpiapi-java", + "version": "5.30.4" + } + ], + "jniDependencies": [ + { + "groupId": "com.ctre.phoenix", + "artifactId": "cci", + "version": "5.30.4", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "cci-sim", + "version": "5.30.4", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenixpro", + "artifactId": "tools", + "version": "23.0.8", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenixpro.sim", + "artifactId": "tools-sim", + "version": "23.0.8", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenixpro.sim", + "artifactId": "simTalonSRX", + "version": "23.0.8", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenixpro.sim", + "artifactId": "simTalonFX", + "version": "23.0.8", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenixpro.sim", + "artifactId": "simVictorSPX", + "version": "23.0.8", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenixpro.sim", + "artifactId": "simPigeonIMU", + "version": "23.0.8", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenixpro.sim", + "artifactId": "simCANCoder", + "version": "23.0.8", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenixpro.sim", + "artifactId": "simProTalonFX", + "version": "23.0.8", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenixpro.sim", + "artifactId": "simProCANcoder", + "version": "23.0.8", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenixpro.sim", + "artifactId": "simProPigeon2", + "version": "23.0.8", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + } + ], + "cppDependencies": [ + { + "groupId": "com.ctre.phoenix", + "artifactId": "wpiapi-cpp", + "version": "5.30.4", + "libName": "CTRE_Phoenix_WPI", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix", + "artifactId": "api-cpp", + "version": "5.30.4", + "libName": "CTRE_Phoenix", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix", + "artifactId": "cci", + "version": "5.30.4", + "libName": "CTRE_PhoenixCCI", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenixpro", + "artifactId": "tools", + "version": "23.0.8", + "libName": "CTRE_PhoenixTools", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "linuxathena" + ], + "simMode": "hwsim" + }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "wpiapi-cpp-sim", + "version": "5.30.4", + "libName": "CTRE_Phoenix_WPISim", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "api-cpp-sim", + "version": "5.30.4", + "libName": "CTRE_PhoenixSim", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenix.sim", + "artifactId": "cci-sim", + "version": "5.30.4", + "libName": "CTRE_PhoenixCCISim", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenixpro.sim", + "artifactId": "tools-sim", + "version": "23.0.8", + "libName": "CTRE_PhoenixTools_Sim", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenixpro.sim", + "artifactId": "simTalonSRX", + "version": "23.0.8", + "libName": "CTRE_SimTalonSRX", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenixpro.sim", + "artifactId": "simTalonFX", + "version": "23.0.8", + "libName": "CTRE_SimTalonFX", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenixpro.sim", + "artifactId": "simVictorSPX", + "version": "23.0.8", + "libName": "CTRE_SimVictorSPX", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenixpro.sim", + "artifactId": "simPigeonIMU", + "version": "23.0.8", + "libName": "CTRE_SimPigeonIMU", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenixpro.sim", + "artifactId": "simCANCoder", + "version": "23.0.8", + "libName": "CTRE_SimCANCoder", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenixpro.sim", + "artifactId": "simProTalonFX", + "version": "23.0.8", + "libName": "CTRE_SimProTalonFX", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenixpro.sim", + "artifactId": "simProCANcoder", + "version": "23.0.8", + "libName": "CTRE_SimProCANcoder", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + }, + { + "groupId": "com.ctre.phoenixpro.sim", + "artifactId": "simProPigeon2", + "version": "23.0.8", + "libName": "CTRE_SimProPigeon2", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ], + "simMode": "swsim" + } + ] +} \ No newline at end of file diff --git a/vendordeps/REVLib.json b/vendordeps/REVLib.json new file mode 100644 index 0000000..f2d0b7d --- /dev/null +++ b/vendordeps/REVLib.json @@ -0,0 +1,73 @@ +{ + "fileName": "REVLib.json", + "name": "REVLib", + "version": "2023.1.3", + "uuid": "3f48eb8c-50fe-43a6-9cb7-44c86353c4cb", + "mavenUrls": [ + "https://maven.revrobotics.com/" + ], + "jsonUrl": "https://software-metadata.revrobotics.com/REVLib-2023.json", + "javaDependencies": [ + { + "groupId": "com.revrobotics.frc", + "artifactId": "REVLib-java", + "version": "2023.1.3" + } + ], + "jniDependencies": [ + { + "groupId": "com.revrobotics.frc", + "artifactId": "REVLib-driver", + "version": "2023.1.3", + "skipInvalidPlatforms": true, + "isJar": false, + "validPlatforms": [ + "windowsx86-64", + "windowsx86", + "linuxarm64", + "linuxx86-64", + "linuxathena", + "linuxarm32", + "osxuniversal" + ] + } + ], + "cppDependencies": [ + { + "groupId": "com.revrobotics.frc", + "artifactId": "REVLib-cpp", + "version": "2023.1.3", + "libName": "REVLib", + "headerClassifier": "headers", + "sharedLibrary": false, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "windowsx86", + "linuxarm64", + "linuxx86-64", + "linuxathena", + "linuxarm32", + "osxuniversal" + ] + }, + { + "groupId": "com.revrobotics.frc", + "artifactId": "REVLib-driver", + "version": "2023.1.3", + "libName": "REVLibDriver", + "headerClassifier": "headers", + "sharedLibrary": false, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "windowsx86", + "linuxarm64", + "linuxx86-64", + "linuxathena", + "linuxarm32", + "osxuniversal" + ] + } + ] +} \ No newline at end of file diff --git a/vendordeps/SdsSwerveLib.json b/vendordeps/SdsSwerveLib.json new file mode 100644 index 0000000..5f1ac5e --- /dev/null +++ b/vendordeps/SdsSwerveLib.json @@ -0,0 +1,19 @@ +{ + "fileName": "SdsSwerveLib.json", + "name": "swerve-lib", + "version": "2023.1.2.2", + "uuid": "9619F7EA-7F96-4236-9D94-02338DFED592", + "mavenUrls": [ + "https://jitpack.io" + ], + "jsonUrl": "https://raw.githubusercontent.com/democat3457/swerve-lib/prod/SdsSwerveLib.json", + "javaDependencies": [ + { + "groupId": "com.github.democat3457", + "artifactId": "swerve-lib", + "version": "2023.1.2.2" + } + ], + "jniDependencies": [], + "cppDependencies": [] +} \ No newline at end of file diff --git a/vendordeps/WPILibNewCommands.json b/vendordeps/WPILibNewCommands.json new file mode 100644 index 0000000..d7bd9b0 --- /dev/null +++ b/vendordeps/WPILibNewCommands.json @@ -0,0 +1,37 @@ +{ + "fileName": "WPILibNewCommands.json", + "name": "WPILib-New-Commands", + "version": "2020.0.0", + "uuid": "111e20f7-815e-48f8-9dd6-e675ce75b266", + "mavenUrls": [], + "jsonUrl": "", + "javaDependencies": [ + { + "groupId": "edu.wpi.first.wpilibNewCommands", + "artifactId": "wpilibNewCommands-java", + "version": "wpilib" + } + ], + "jniDependencies": [], + "cppDependencies": [ + { + "groupId": "edu.wpi.first.wpilibNewCommands", + "artifactId": "wpilibNewCommands-cpp", + "version": "wpilib", + "libName": "wpilibNewCommands", + "headerClassifier": "headers", + "sourcesClassifier": "sources", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena", + "linuxraspbian", + "linuxaarch64bionic", + "windowsx86-64", + "windowsx86", + "linuxx86-64", + "osxx86-64" + ] + } + ] +} diff --git a/vendordeps/photonlib.json b/vendordeps/photonlib.json new file mode 100644 index 0000000..dad3105 --- /dev/null +++ b/vendordeps/photonlib.json @@ -0,0 +1,41 @@ +{ + "fileName": "photonlib.json", + "name": "photonlib", + "version": "v2023.4.2", + "uuid": "515fe07e-bfc6-11fa-b3de-0242ac130004 ", + "mavenUrls": [ + "https://maven.photonvision.org/repository/internal", + "https://maven.photonvision.org/repository/snapshots" + ], + "jsonUrl": "https://maven.photonvision.org/repository/internal/org/photonvision/PhotonLib-json/1.0/PhotonLib-json-1.0.json", + "jniDependencies": [], + "cppDependencies": [ + { + "groupId": "org.photonvision", + "artifactId": "PhotonLib-cpp", + "version": "v2023.4.2", + "libName": "Photon", + "headerClassifier": "headers", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxathena", + "linuxx86-64", + "osxuniversal" + ] + } + ], + "javaDependencies": [ + { + "groupId": "org.photonvision", + "artifactId": "PhotonLib-java", + "version": "v2023.4.2" + }, + { + "groupId": "org.photonvision", + "artifactId": "PhotonTargeting-java", + "version": "v2023.4.2" + } + ] +} \ No newline at end of file diff --git a/vendordeps/playingwithfusion2023.json b/vendordeps/playingwithfusion2023.json new file mode 100644 index 0000000..c64749f --- /dev/null +++ b/vendordeps/playingwithfusion2023.json @@ -0,0 +1,70 @@ +{ + "fileName": "playingwithfusion2023.json", + "name": "PlayingWithFusion", + "version": "2023.01.17", + "uuid": "14b8ad04-24df-11ea-978f-2e728ce88125", + "jsonUrl": "https://www.playingwithfusion.com/frc/playingwithfusion2023.json", + "mavenUrls": [ + "https://www.playingwithfusion.com/frc/maven/" + ], + "javaDependencies": [ + { + "groupId": "com.playingwithfusion.frc", + "artifactId": "PlayingWithFusion-java", + "version": "2023.01.17" + } + ], + "jniDependencies": [ + { + "groupId": "com.playingwithfusion.frc", + "artifactId": "PlayingWithFusion-driver", + "version": "2023.01.17", + "isJar": false, + "skipInvalidPlatforms": true, + "validPlatforms": [ + "linuxathena", + "linuxraspbian", + "linuxaarch64bionic", + "windowsx86-64", + "linuxx86-64", + "osxx86-64" + ] + } + ], + "cppDependencies": [ + { + "groupId": "com.playingwithfusion.frc", + "artifactId": "PlayingWithFusion-cpp", + "version": "2023.01.17", + "headerClassifier": "headers", + "sharedLibrary": false, + "libName": "PlayingWithFusion", + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena", + "linuxraspbian", + "linuxaarch64bionic", + "windowsx86-64", + "linuxx86-64", + "osxx86-64" + ] + }, + { + "groupId": "com.playingwithfusion.frc", + "artifactId": "PlayingWithFusion-driver", + "version": "2023.01.17", + "headerClassifier": "headers", + "sharedLibrary": true, + "libName": "PlayingWithFusionDriver", + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena", + "linuxraspbian", + "linuxaarch64bionic", + "windowsx86-64", + "linuxx86-64", + "osxx86-64" + ] + } + ] +} \ No newline at end of file