diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..d1638be
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,7 @@
+*.gradle text eol=lf
+*.java text eol=lf
+*.md text eol=lf
+*.xml text eol=lf
+*.fxml text eol=lf
+*.yml text eol=lf
+*.yaml 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..d187852
--- /dev/null
+++ b/.github/workflows/gradle.yml
@@ -0,0 +1,26 @@
+name: Java CI
+
+on: [push]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ build:
+ strategy:
+ fail-fast: false
+ matrix:
+ platform: [ubuntu-latest, macos-latest, windows-latest]
+ runs-on: ${{ matrix.platform }}
+
+ steps:
+ - uses: actions/checkout@v1
+
+ - name: Set up Java
+ uses: actions/setup-java@v1
+ with:
+ java-version: 1.11
+
+ - name: Build Everything
+ run: ./gradlew build
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..85fee61
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,338 @@
+# Created by https://www.toptal.com/developers/gitignore/api/java,linux,macos,gradle,eclipse,windows,netbeans,intellij+iml,visualstudiocode
+# Edit at https://www.toptal.com/developers/gitignore?templates=java,linux,macos,gradle,eclipse,windows,netbeans,intellij+iml,visualstudiocode
+
+### Eclipse ###
+.metadata
+bin/
+tmp/
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.settings/
+.loadpath
+.recommenders
+
+# External tool builders
+.externalToolBuilders/
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# PyDev specific (Python IDE for Eclipse)
+*.pydevproject
+
+# CDT-specific (C/C++ Development Tooling)
+.cproject
+
+# CDT- autotools
+.autotools
+
+# Java annotation processor (APT)
+.factorypath
+
+# PDT-specific (PHP Development Tools)
+.buildpath
+
+# sbteclipse plugin
+.target
+
+# Tern plugin
+.tern-project
+
+# TeXlipse plugin
+.texlipse
+
+# STS (Spring Tool Suite)
+.springBeans
+
+# Code Recommenders
+.recommenders/
+
+# Annotation Processing
+.apt_generated/
+.apt_generated_test/
+
+# Scala IDE specific (Scala & Java development for Eclipse)
+.cache-main
+.scala_dependencies
+.worksheet
+
+# Uncomment this line if you wish to ignore the project description file.
+# Typically, this file would be tracked if it contains build/dependency configurations:
+#.project
+
+### Eclipse Patch ###
+# Spring Boot Tooling
+.sts4-cache/
+
+### Intellij+iml ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# AWS User-specific
+.idea/**/aws.xml
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+.idea/artifacts
+.idea/compiler.xml
+.idea/jarRepositories.xml
+.idea/modules.xml
+.idea/*.iml
+.idea/modules
+*.iml
+*.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# SonarLint plugin
+.idea/sonarlint/
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### Intellij+iml Patch ###
+# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
+
+*.iml
+modules.xml
+.idea/misc.xml
+*.ipr
+
+### Java ###
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+replay_pid*
+
+### 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
+
+### macOS Patch ###
+# iCloud generated files
+*.icloud
+
+### NetBeans ###
+**/nbproject/private/
+**/nbproject/Makefile-*.mk
+**/nbproject/Package-*.bash
+build/
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/
+
+### VisualStudioCode ###
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+!.vscode/*.code-snippets
+
+# Local History for Visual Studio Code
+.history/
+
+# Built Visual Studio Code Extensions
+*.vsix
+
+### VisualStudioCode Patch ###
+# Ignore all local history of files
+.history
+.ionide
+
+# Support for Project snippet scope
+.vscode/*.code-snippets
+
+# Ignore code-workspaces
+*.code-workspace
+
+### Windows ###
+# Windows thumbnail cache files
+Thumbs.db
+Thumbs.db:encryptable
+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/
+!src/**/build/
+
+# Ignore Gradle GUI config
+gradle-app.setting
+
+# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
+!gradle-wrapper.jar
+
+# Avoid ignore Gradle wrappper properties
+!gradle-wrapper.properties
+
+# Cache of project
+.gradletasknamecache
+
+# Eclipse Gradle plugin generated files
+# Eclipse Core
+.project
+# JDT-specific (Eclipse Java Development Tools)
+.classpath
+
+# End of https://www.toptal.com/developers/gitignore/api/java,linux,macos,gradle,eclipse,windows,netbeans,intellij+iml,visualstudiocode
+
+
+
+# === Entries from WPI Lib team ===
+# The following gitignore entries have been specially created by the WPI Lib development team.
+# If you remove items from this file, intellisense might break.
+
+# # 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
+
+# End entries from WPI Lib team
+
+simgui.json
+
+.idea/codeStyles/
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..15a15b2
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..40b9d9f
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/Build & Deploy Robot for Debugging.run.xml b/.run/Build & Deploy Robot for Debugging.run.xml
new file mode 100644
index 0000000..32b8fa5
--- /dev/null
+++ b/.run/Build & Deploy Robot for Debugging.run.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+ false
+
+
+
\ No newline at end of file
diff --git a/.run/Build & Deploy Robot.run.xml b/.run/Build & Deploy Robot.run.xml
new file mode 100644
index 0000000..0bc525a
--- /dev/null
+++ b/.run/Build & Deploy Robot.run.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+ false
+
+
+
\ No newline at end of file
diff --git a/.run/Build Robot.run.xml b/.run/Build Robot.run.xml
new file mode 100644
index 0000000..bf8bc83
--- /dev/null
+++ b/.run/Build Robot.run.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+ false
+
+
+
\ No newline at end of file
diff --git a/.run/Clean Build & Deploy Robot for Debugging.run.xml b/.run/Clean Build & Deploy Robot for Debugging.run.xml
new file mode 100644
index 0000000..dde4f54
--- /dev/null
+++ b/.run/Clean Build & Deploy Robot for Debugging.run.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+ false
+
+
+
\ No newline at end of file
diff --git a/.run/Clean Build & Deploy Robot.run.xml b/.run/Clean Build & Deploy Robot.run.xml
new file mode 100644
index 0000000..1c31fd2
--- /dev/null
+++ b/.run/Clean Build & Deploy Robot.run.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+ false
+
+
+
\ No newline at end of file
diff --git a/.run/Clean Build Robot.run.xml b/.run/Clean Build Robot.run.xml
new file mode 100644
index 0000000..7d68d3f
--- /dev/null
+++ b/.run/Clean Build Robot.run.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+ false
+
+
+
\ No newline at end of file
diff --git a/.run/Debug Robot via IP.run.xml b/.run/Debug Robot via IP.run.xml
new file mode 100644
index 0000000..21aa5b4
--- /dev/null
+++ b/.run/Debug Robot via IP.run.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/Debug Robot via USB.run.xml b/.run/Debug Robot via USB.run.xml
new file mode 100644
index 0000000..6e25195
--- /dev/null
+++ b/.run/Debug Robot via USB.run.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/Simulate.run.xml b/.run/Simulate.run.xml
new file mode 100644
index 0000000..78d07b2
--- /dev/null
+++ b/.run/Simulate.run.xml
@@ -0,0 +1,23 @@
+
+
+
+
It is advised to statically import this class (or one of its inner classes) wherever the
+ * constants are needed, to reduce verbosity.
+ */
+public final class Constants {
+ public static final int DRIVE_LEFT_A = 0;
+ public static final int DRIVE_LEFT_B = 1;
+ public static final int DRIVE_RIGHT_A = 2;
+ public static final int DRIVE_RIGHT_B = 3;
+}
diff --git a/src/main/java/com/scra/codelabs/gitflow/Main.java b/src/main/java/com/scra/codelabs/gitflow/Main.java
new file mode 100644
index 0000000..56d0134
--- /dev/null
+++ b/src/main/java/com/scra/codelabs/gitflow/Main.java
@@ -0,0 +1,26 @@
+// Copyright (c) FIRST and other WPILib contributors.
+
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+package com.scra.codelabs.gitflow;
+
+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 method. Do not perform any initialization here.
+ *
+ * If you change your main Robot class (name), change the parameter type.
+ */
+ public static void main(String... args) {
+ RobotBase.startRobot(Robot::new);
+ }
+}
diff --git a/src/main/java/com/scra/codelabs/gitflow/Robot.java b/src/main/java/com/scra/codelabs/gitflow/Robot.java
new file mode 100644
index 0000000..4ee344f
--- /dev/null
+++ b/src/main/java/com/scra/codelabs/gitflow/Robot.java
@@ -0,0 +1,122 @@
+// 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 com.scra.codelabs.gitflow;
+
+import edu.wpi.first.wpilibj.TimedRobot;
+import edu.wpi.first.wpilibj2.command.Command;
+import edu.wpi.first.wpilibj2.command.CommandScheduler;
+
+
+/**
+ * The VM is configured to automatically run this class, and to call the methods corresponding to
+ * each mode, as described in the TimedRobot documentation. If you change the name of this class or
+ * the package after creating this project, you must also update the build.gradle file in the
+ * project.
+ */
+public class Robot extends TimedRobot {
+ private Command m_autonomousCommand;
+
+ private RobotContainer m_robotContainer;
+
+
+ /**
+ * This method is run when the robot is first started up and should be used for any
+ * initialization code.
+ */
+ @Override
+ public void robotInit() {
+ // Instantiate our RobotContainer. This will perform all our button bindings, and put our
+ // autonomous chooser on the dashboard.
+ m_robotContainer = new RobotContainer();
+ }
+
+
+ /**
+ * This method 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 methods, 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 method is called once each time the robot enters Disabled mode.
+ */
+ @Override
+ public void disabledInit() {
+ }
+
+
+ @Override
+ public void disabledPeriodic() {
+ }
+
+
+ /**
+ * This autonomous runs the autonomous command selected by your {@link RobotContainer} class.
+ */
+ @Override
+ public void autonomousInit() {
+ m_autonomousCommand = m_robotContainer.getAutonomousCommand();
+
+ // schedule the autonomous command (example)
+ if (m_autonomousCommand != null) {
+ m_autonomousCommand.schedule();
+ }
+ }
+
+
+ /**
+ * This method is called periodically during autonomous.
+ */
+ @Override
+ public void autonomousPeriodic() {
+ }
+
+
+ @Override
+ public void teleopInit() {
+ // This makes sure that the autonomous stops running when
+ // teleop starts running. If you want the autonomous to
+ // continue until interrupted by another command, remove
+ // this line or comment it out.
+ if (m_autonomousCommand != null) {
+ m_autonomousCommand.cancel();
+ }
+ }
+
+
+ /**
+ * This method is called periodically during operator control.
+ */
+ @Override
+ public void teleopPeriodic() {
+ }
+
+
+ @Override
+ public void testInit() {
+ // Cancels all running commands at the start of test mode.
+ CommandScheduler.getInstance().cancelAll();
+ }
+
+
+ /**
+ * This method is called periodically during test mode.
+ */
+ @Override
+ public void testPeriodic() {
+ }
+}
diff --git a/src/main/java/com/scra/codelabs/gitflow/RobotContainer.java b/src/main/java/com/scra/codelabs/gitflow/RobotContainer.java
new file mode 100644
index 0000000..967c16d
--- /dev/null
+++ b/src/main/java/com/scra/codelabs/gitflow/RobotContainer.java
@@ -0,0 +1,90 @@
+// 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 com.scra.codelabs.gitflow;
+
+import com.scra.codelabs.gitflow.commands.PJExampleCommand;
+import com.scra.codelabs.gitflow.commands.TeleopDriveCommand;
+import com.scra.codelabs.gitflow.subsystems.ChassisSubsystem;
+import edu.wpi.first.wpilibj.GenericHID;
+import edu.wpi.first.wpilibj.XboxController;
+import edu.wpi.first.wpilibj2.command.Command;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * 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.
+ */
+@SuppressWarnings("PMD.UnusedPrivateField")
+public class RobotContainer {
+ private static final String DRIVETRAIN_NAME = "m_drivetrain";
+
+ private PJExampleCommand m_pjExample;
+
+ ///////////////////////////////////////
+ // Don't touch things below here
+ ///////////////////////////////////////
+
+ private final ChassisSubsystem m_drivetrain;
+
+ /**
+ * The container for the robot. Contains subsystems, OI devices, and commands.
+ */
+ public RobotContainer() {
+ m_drivetrain = new ChassisSubsystem();
+
+ Field[] fields = RobotContainer.class.getDeclaredFields();
+
+ List sortedNames = new ArrayList<>();
+ for (Field field : fields) {
+ if (!DRIVETRAIN_NAME.equals(field.getName())) {
+ sortedNames.add(field.getType().getName());
+ }
+ }
+
+ sortedNames.sort(String::compareTo);
+
+ System.out.println("\n\n\n\n********************************************************");
+ for (String className : sortedNames) {
+ try {
+ Class> clazz = Class.forName(className);
+ clazz.getDeclaredConstructor().newInstance();
+ } catch (ClassNotFoundException | IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
+ e.printStackTrace(); // NOPMD
+ }
+ }
+ System.out.println("********************************************************\n\n\n\n");
+
+ // Configure the button bindings
+ configureButtonBindings();
+ }
+
+ /**
+ * Use this method to define your button->command mappings. Buttons can be created by
+ * instantiating a {@link GenericHID} or one of its subclasses ({@link
+ * edu.wpi.first.wpilibj.Joystick Joystick} or {@link XboxController}), and then passing it to a
+ * {@link edu.wpi.first.wpilibj2.command.button.JoystickButton JoystickButton}.
+ */
+ private void configureButtonBindings() {
+ m_drivetrain.setDefaultCommand(new TeleopDriveCommand(m_drivetrain));
+ }
+
+
+ /**
+ * Use this to pass the autonomous command to the main {@link Robot} class.
+ *
+ * @return the command to run in autonomous
+ */
+ public Command getAutonomousCommand() {
+ return null;
+ }
+}
diff --git a/src/main/java/com/scra/codelabs/gitflow/commands/PJExampleCommand.java b/src/main/java/com/scra/codelabs/gitflow/commands/PJExampleCommand.java
new file mode 100644
index 0000000..1215426
--- /dev/null
+++ b/src/main/java/com/scra/codelabs/gitflow/commands/PJExampleCommand.java
@@ -0,0 +1,15 @@
+package com.scra.codelabs.gitflow.commands;
+
+import edu.wpi.first.wpilibj2.command.CommandBase;
+
+
+public class PJExampleCommand extends CommandBase {
+
+ public PJExampleCommand() {
+ // each subsystem used by the command must be passed into the
+ // addRequirements() method (which takes a vararg of Subsystem)
+ addRequirements();
+
+ System.out.println("PJ makes an example");
+ }
+}
diff --git a/src/main/java/com/scra/codelabs/gitflow/commands/TeleopDriveCommand.java b/src/main/java/com/scra/codelabs/gitflow/commands/TeleopDriveCommand.java
new file mode 100644
index 0000000..f878444
--- /dev/null
+++ b/src/main/java/com/scra/codelabs/gitflow/commands/TeleopDriveCommand.java
@@ -0,0 +1,38 @@
+package com.scra.codelabs.gitflow.commands;
+
+import com.scra.codelabs.gitflow.subsystems.ChassisSubsystem;
+import edu.wpi.first.wpilibj.XboxController;
+import edu.wpi.first.wpilibj2.command.CommandBase;
+
+
+public class TeleopDriveCommand extends CommandBase {
+ private final XboxController m_joystick;
+ private final ChassisSubsystem m_chassisSubsystem;
+
+ public TeleopDriveCommand(ChassisSubsystem chassisSubsystem) {
+ m_chassisSubsystem = chassisSubsystem;
+ m_joystick = new XboxController(0);
+
+ addRequirements(this.m_chassisSubsystem);
+ }
+
+ @Override
+ public void initialize() {
+
+ }
+
+ @Override
+ public void execute() {
+ m_chassisSubsystem.arcadeDrive(-m_joystick.getLeftY(), m_joystick.getRightX());
+ }
+
+ @Override
+ public boolean isFinished() {
+ return false;
+ }
+
+ @Override
+ public void end(boolean interrupted) {
+
+ }
+}
diff --git a/src/main/java/com/scra/codelabs/gitflow/subsystems/ChassisSubsystem.java b/src/main/java/com/scra/codelabs/gitflow/subsystems/ChassisSubsystem.java
new file mode 100644
index 0000000..ab8ad78
--- /dev/null
+++ b/src/main/java/com/scra/codelabs/gitflow/subsystems/ChassisSubsystem.java
@@ -0,0 +1,41 @@
+package com.scra.codelabs.gitflow.subsystems;
+
+
+import com.scra.codelabs.gitflow.Constants;
+import edu.wpi.first.wpilibj.drive.DifferentialDrive;
+import edu.wpi.first.wpilibj.motorcontrol.MotorController;
+import edu.wpi.first.wpilibj.motorcontrol.MotorControllerGroup;
+import edu.wpi.first.wpilibj.motorcontrol.Talon;
+import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
+import edu.wpi.first.wpilibj2.command.SubsystemBase;
+
+public class ChassisSubsystem extends SubsystemBase {
+
+ private final MotorController m_leftDriveA;
+ private final MotorController m_rightDriveA;
+
+ private final DifferentialDrive m_differentialDrive;
+
+ @SuppressWarnings("PMD.CloseResource")
+ public ChassisSubsystem() {
+
+ m_leftDriveA = new Talon(Constants.DRIVE_LEFT_A);
+ m_rightDriveA = new Talon(Constants.DRIVE_RIGHT_A);
+
+ MotorController leftDriveB = new Talon(Constants.DRIVE_LEFT_B);
+ MotorController rightDriveB = new Talon(Constants.DRIVE_RIGHT_B);
+
+ m_differentialDrive = new DifferentialDrive(new MotorControllerGroup(m_leftDriveA, leftDriveB),
+ new MotorControllerGroup(m_rightDriveA, rightDriveB));
+ }
+
+ public void arcadeDrive(double speed, double steer) {
+ m_differentialDrive.arcadeDrive(speed, steer);
+ }
+
+ @Override
+ public void periodic() {
+ SmartDashboard.putNumber("Left Drive", m_leftDriveA.get());
+ SmartDashboard.putNumber("Right Drive", m_rightDriveA.get());
+ }
+}
diff --git a/styleguide/checkstyle.xml b/styleguide/checkstyle.xml
new file mode 100644
index 0000000..b6983ec
--- /dev/null
+++ b/styleguide/checkstyle.xml
@@ -0,0 +1,244 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/styleguide/pmd-ruleset.xml b/styleguide/pmd-ruleset.xml
new file mode 100644
index 0000000..e1edfde
--- /dev/null
+++ b/styleguide/pmd-ruleset.xml
@@ -0,0 +1,114 @@
+
+
+
+ PMD Ruleset for Girls of Steel
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/styleguide/spotless.gradle b/styleguide/spotless.gradle
new file mode 100644
index 0000000..82869d0
--- /dev/null
+++ b/styleguide/spotless.gradle
@@ -0,0 +1,47 @@
+
+apply plugin: 'com.diffplug.spotless'
+
+
+spotless {
+ java {
+ target fileTree('.') {
+ include '**/*.java'
+ exclude '**/build/**', '**/build-*/**', 'bazel-*/**', '**/venv/**'
+ }
+ toggleOffOn()
+ indentWithSpaces(4)
+ removeUnusedImports()
+ trimTrailingWhitespace()
+ endWithNewline()
+ }
+ groovyGradle {
+ target fileTree('.') {
+ include '**/*.gradle'
+ exclude '**/build/**', '**/build-*/**', 'bazel-*/**', '**/venv/**'
+ }
+ greclipse()
+ indentWithSpaces(4)
+ trimTrailingWhitespace()
+ endWithNewline()
+ }
+ format 'xml', {
+ target fileTree('.') {
+ include '**/*.xml'
+ include '**/*.fxml'
+ exclude '**/build/**', '**/build-*/**', '**/bazel-*/**', '**/.idea/**', '**/.run/**', '**/venv/**'
+ }
+ eclipseWtp('xml')
+ trimTrailingWhitespace()
+ indentWithSpaces(4)
+ endWithNewline()
+ }
+ format 'misc', {
+ target fileTree('.') {
+ include '**/*.md', '**/.gitignore', "**/*.yml", "**/*.yaml"
+ exclude '**/build/**', '**/build-*/**', 'bazel-*/**', '**/venv/**'
+ }
+ trimTrailingWhitespace()
+ indentWithSpaces(4)
+ endWithNewline()
+ }
+}
diff --git a/styleguide/styleguide.gradle b/styleguide/styleguide.gradle
new file mode 100644
index 0000000..f982586
--- /dev/null
+++ b/styleguide/styleguide.gradle
@@ -0,0 +1,18 @@
+
+apply plugin: 'checkstyle'
+apply plugin: 'pmd'
+
+checkstyle {
+ toolVersion = "10.0"
+ configDirectory.set(file("${project.rootDir}/styleguide"))
+}
+
+pmd {
+ toolVersion = '6.43.0'
+ consoleOutput = true
+ reportsDir = file("${project.buildDir}/reports/pmd")
+ ruleSetFiles = files(file("$rootDir/styleguide/pmd-ruleset.xml"))
+ ruleSets = []
+}
+
+// apply from: "${rootDir}/styleguide/spotless.gradle"
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"
+ ]
+ }
+ ]
+}