diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..939574d8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,7 @@ +[*{json,yml,yaml,js,ts,css,html}] +end_of_line = lf +indent_size = 2 + +[*{java}] +end_of_line = lf +indent_size = 4 \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..bed58fc0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,16 @@ +* text=auto + +.* text eol=lf +*.json text eol=lf +*.yml text eol=lf +*.yaml text eol=lf +*.js text eol=lf +*.ts text eol=lf +*.css text eol=lf +*.html text eol=lf +*.java text eol=lf +src/main/ts/** text eol=lf + +*.bat text eol=crlf + +*.jpg binary diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2bceecd3..32bca15b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,7 +13,7 @@ jobs: container: wpilib/roborio-cross-ubuntu:2024-22.04 steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Grant execute permission run: chmod +x gradlew - name: Check formatting diff --git a/.gitignore b/.gitignore index 160925a9..127dcae3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,193 +1,193 @@ -# 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 - -### 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/ - -# IntelliJ -*.iml -*.ipr -*.iws -.idea/ -out/ - -# Fleet -.fleet - -# Simulation GUI and other tools window save file -*-window.json -simgui*.json -networktables.json -networktables.json.bck - -# Version file -src/main/java/com/team1701/robot/BuildConstants.java - -# Simulation data log directory -logs/ - -# Folder that has CTRE Phoenix Sim device config storage -ctre_sim/ - -################# -### Team 1701 ### -################# - -# Node -node_modules -dist -src/main/deploy/web +# 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 + +### 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/ + +# IntelliJ +*.iml +*.ipr +*.iws +.idea/ +out/ + +# Fleet +.fleet + +# Simulation GUI and other tools window save file +*-window.json +simgui*.json +networktables.json +networktables.json.bck + +# Version file +src/main/java/com/team1701/robot/BuildConstants.java + +# Simulation data log directory +logs/ + +# Folder that has CTRE Phoenix Sim device config storage +ctre_sim/ + +################# +### Team 1701 ### +################# + +# Node +node_modules +dist +src/main/deploy/web diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7015f6be..5e82d67b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=permwrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip -networkTimeout=10000 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=permwrapper/dists +distributionBase=GRADLE_USER_HOME +distributionPath=permwrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=permwrapper/dists diff --git a/gradlew b/gradlew old mode 100755 new mode 100644 diff --git a/gradlew.bat b/gradlew.bat index 6689b85b..93e3f59f 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,92 +1,92 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/src/main/java/com/team1701/lib/util/GeometryUtil.java b/src/main/java/com/team1701/lib/util/GeometryUtil.java index ad72c166..cc5de7c8 100644 --- a/src/main/java/com/team1701/lib/util/GeometryUtil.java +++ b/src/main/java/com/team1701/lib/util/GeometryUtil.java @@ -21,7 +21,16 @@ public final class GeometryUtil { public static final Rotation3d kRotation3dIdentity = new Rotation3d(); public static Rotation2d flipX(Rotation2d rotation) { - return rotation.getRadians() < 0 ? kRotationMinusPi.minus(rotation) : kRotationPi.minus(rotation); + return kRotationPi.minus(rotation); + } + + public static Pose2d flipX(Pose2d pose, double fieldLength) { + return new Pose2d(fieldLength - pose.getX(), pose.getY(), flipX(pose.getRotation())); + } + + public static Pose2d[] flipX(Pose2d[] poses, double fieldLength) { + // TODO: Flip poses + return poses; } public static Rotation2d angleModulus(Rotation2d rotation) { diff --git a/src/main/java/com/team1701/lib/util/PathBuilder.java b/src/main/java/com/team1701/lib/util/PathBuilder.java new file mode 100644 index 00000000..c83e6f7b --- /dev/null +++ b/src/main/java/com/team1701/lib/util/PathBuilder.java @@ -0,0 +1,41 @@ +package com.team1701.lib.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.pathplanner.lib.path.PathPlannerPath; +import edu.wpi.first.math.geometry.Pose2d; + +public class PathBuilder { + private final List mPath = new ArrayList<>(); + + public Pose2d[] build() { + return mPath.toArray(new Pose2d[mPath.size()]); + } + + public Pose2d[] buildAndClear() { + var path = build(); + clear(); + return path; + } + + public void clear() { + mPath.clear(); + } + + public PathBuilder addPose(Pose2d pose) { + // TODO: Add to mPath + return this; + } + + public PathBuilder addPath(Pose2d[] path) { + Collections.addAll(mPath, path); + return this; + } + + public PathBuilder addPath(PathPlannerPath path) { + // TODO: Add to mPath + return this; + } +} diff --git a/src/main/java/com/team1701/robot/RobotContainer.java b/src/main/java/com/team1701/robot/RobotContainer.java index eaebdaa2..c9da0de1 100644 --- a/src/main/java/com/team1701/robot/RobotContainer.java +++ b/src/main/java/com/team1701/robot/RobotContainer.java @@ -170,10 +170,37 @@ private void setupAutonomous() { PathPlannerLogging.setLogActivePathCallback( poses -> Logger.recordOutput("PathPlanner/Path", poses.toArray(Pose2d[]::new))); + // TODO: Create wrapper class for autonomous chooser + // TODO: Also update on change to team color var commands = new AutonomousCommands(mRobotState, mDrive); - autonomousModeChooser.addDefaultOption("Demo", commands.demo()); - autonomousModeChooser.addOption("Four Piece", commands.fourPiece()); + var demoCommand = commands.demo(); + var fourPieceCommand = commands.fourPiece(); + + autonomousModeChooser.addDefaultOption("Demo", demoCommand.command()); + autonomousModeChooser.addOption("Four Piece", fourPieceCommand.command()); autonomousModeChooser.addOption("Four Piece Planner", new PathPlannerAuto("FourPiece")); + + autonomousModeChooser.getSendableChooser().onChange(name -> { + Pose2d[] path; + switch (name) { + case "Demo": + path = demoCommand.path(); + break; + case "Four Piece": + path = fourPieceCommand.path(); + break; + default: + path = new Pose2d[] {}; + break; + } + + if (Configuration.isRedAlliance()) { + path = GeometryUtil.flipX(path, FieldConstants.kFieldLongLengthMeters); + } + + // TODO: Also export as Translation2d[] + Logger.recordOutput("Autonomous/PathPose2d", path); + }); } private void setupStateTriggers() { diff --git a/src/main/java/com/team1701/robot/commands/AutonomousCommands.java b/src/main/java/com/team1701/robot/commands/AutonomousCommands.java index 9a1d076c..cb7874e6 100644 --- a/src/main/java/com/team1701/robot/commands/AutonomousCommands.java +++ b/src/main/java/com/team1701/robot/commands/AutonomousCommands.java @@ -8,6 +8,7 @@ import com.pathplanner.lib.path.PathPlannerPath; import com.team1701.lib.swerve.SwerveSetpointGenerator.KinematicLimits; import com.team1701.lib.util.GeometryUtil; +import com.team1701.lib.util.PathBuilder; import com.team1701.robot.Configuration; import com.team1701.robot.Constants; import com.team1701.robot.FieldConstants; @@ -23,6 +24,13 @@ public class AutonomousCommands { private final RobotState mRobotState; private final Drive mDrive; + private PathBuilder mPathBuilder = new PathBuilder(); + + public static record AutonomousCommand(Command command, Pose2d[] path) { + public AutonomousCommand(Command command) { + this(command, new Pose2d[] {}); + } + } public AutonomousCommands(RobotState robotState, Drive drive) { mRobotState = robotState; @@ -32,10 +40,7 @@ public AutonomousCommands(RobotState robotState, Drive drive) { } private Pose2d autoFlipPose(Pose2d pose) { - var flippedPose = new Pose2d( - FieldConstants.kFieldLongLengthMeters - pose.getX(), - pose.getY(), - GeometryUtil.kRotationPi.minus(pose.getRotation())); + var flippedPose = GeometryUtil.flipX(pose, FieldConstants.kFieldLongLengthMeters); return Configuration.isRedAlliance() ? flippedPose : pose; } @@ -93,11 +98,13 @@ private Command followChoreoPath(String pathName, boolean resetPose) { return idle(); // Prevent auto mode from continuing if trajectory failed to load } + mPathBuilder.addPath(trajectory.getPoses()); + return new DriveChoreoTrajectory(mDrive, trajectory, mRobotState, resetPose); } - public Command demo() { - return loggedSequence( + public AutonomousCommand demo() { + var command = loggedSequence( print("Starting demo"), followPath("demo1", true), driveToPose(new Pose2d(2.0, 1.0, Rotation2d.fromRadians(-Math.PI * 2.0 / 3.0))), @@ -108,13 +115,17 @@ public Command demo() { followPath("demo2"), driveToPose(new Pose2d(10.0, 5.0, GeometryUtil.kRotationMinusHalfPi), false)) .withName("AutonomousDemo"); + + return new AutonomousCommand(command, new Pose2d[] {}); // TODO: Add path } - public Command fourPiece() { - return loggedSequence( + public AutonomousCommand fourPiece() { + var command = loggedSequence( print("Started four piece auto"), followChoreoPath("FourPiece.1", true), followChoreoPath("FourPiece.2"), followChoreoPath("FourPiece.3")); + + return new AutonomousCommand(command, mPathBuilder.buildAndClear()); } }