Java/WPILib command-based robot code for Team 5190's 2026 robot. The active stack is a YAGSL-based swerve drivetrain with Limelight vision, a turreted shooter, REV motor controllers, and PathPlanner autonomous routines.
The repository already has the main robot skeleton in place:
- field-oriented swerve teleop driving
- PathPlanner auto loading
- Limelight-backed vision data
- intake, indexer, and turret subsystems
- a
ShootOnTheMoveprototype that blends odometry and vision
It is still an in-progress branch, not a cleaned competition release. The biggest issues to know up front are:
src/main/java/frc/robot/commands/ShootAuto.javais incomplete and may prevent a clean build- WPILib template files are still present (
Autos,ExampleCommand,ExampleSubsystem) RobotContaineruses controller port1whileConstants.javasays0Constants.maximumSpeedis set toUnits.feetToMeters(1), which is likely a placeholderTurretrotation uses CAN ID17, andsrc/main/deploy/swerve/swervedrive.jsonalso assigns17to the Pigeon2 IMU
This project uses GradleRIO 2026.2.1 and targets Java 17. The wrapper in this checkout is not executable, so the safest invocation is:
bash gradlew build
bash gradlew test
bash gradlew simulateJava
bash gradlew deployDeployment uses team 5190 from .wpilib/wpilib_preferences.json. Desktop and roboRIO debug launch profiles live in .vscode/launch.json.
src/main/java/frc/robot/Main.javais the standard WPILib entry point and only callsRobotBase.startRobot(Robot::new).src/main/java/frc/robot/Robot.javais a thinTimedRobotshell. It creates oneRobotContainer, runsCommandSchedulerinrobotPeriodic(), schedules the selected autonomous command inautonomousInit(), cancels it inteleopInit(), and cancels everything intestInit().- Most former Limelight and SmartDashboard debug code in
Robot.javais commented out rather than removed.
src/main/java/frc/robot/RobotContainer.java is the composition root. It instantiates:
SwerveSubsystemVisionSubsystemIntakeIndexerTurretSuperstructure
It also defines the default drive command, controller bindings, alliance-specific shooting targets, and the autonomous sequence.
The default drive command is built from SwerveInputStream:
- left stick Y/X drive translation
- right stick X controls rotation
- deadband comes from
OperatorConstants.DEADBAND(0.05) - translation is scaled to
0.8 - alliance-relative control is enabled
driveDirectAngle also exists, but it is currently unused.
Current active bindings in RobotContainer are:
A: intake roller forward viasuperstructure.jogRoller(0.6)B: intake roller reverse viasuperstructure.jogRoller(-0.6)Right Bumper: intake extension out viasuperstructure.jogExtension(0.2)Left Bumper: intake extension in viasuperstructure.jogExtension(-0.2)Left Trigger: runnew ShootOnTheMove(turret, drivebase, vision, getShootTarget())
Commented-out bindings show intended future operator flows for:
- indexer jogging
- AprilTag-assisted drive alignment to specific field tags
Superstructure is a thin command factory, not a full finite-state machine. It wraps subsystem actions into schedulable commands using StartEndCommand and RunCommand(...).until(...).
Available helpers:
jogRollerjogExtensionjogIndexerrunFlywheeljogHoodUpjogHoodDownsetHoodPositionjogRotationLeftjogRotationRightsetRotationPositionautoAim
autoAim() only rotates the turret from vision input. It does not command hood, flywheel, or indexer, so it is only a partial aiming utility.
This command is a simple AprilTag alignment loop for the turret:
- if no tag is visible, the turret rotates slowly to search
- if a tag is visible,
vision.getTX()is multiplied bykP = 0.02 - the command ends when horizontal error is within
1.0degree
This is the most advanced behavior in the repo. Each cycle it:
- reads field-relative chassis velocity from the swerve drive
- latency-compensates the robot pose
- estimates shot distance from Limelight target-space data or odometry fallback
- interpolates flywheel output from a three-point distance table
- computes a compensated shot vector that accounts for robot motion
- derives turret heading and hood pitch from that shot vector
- commands turret rotation, hood position, and flywheel output
It runs until interrupted. The structure is strong, but the constants and interpolation table are clearly marked as tune-on-robot values.
This file is intended to implement an autonomous shot sequence:
- align turret to an AprilTag
- spin up the flywheel
- wait for speed
- run the indexer
- stop motors
Right now it is not complete:
- the method signature omits
VisionSubsystem - the body still references
vision withTimeoutis misspelled aswithTimout- closing syntax is missing
RobotContainer still calls it from autonomous, so this is the main code path to repair before relying on auto shooting.
These files are still stock WPILib scaffolding:
src/main/java/frc/robot/commands/Autos.javasrc/main/java/frc/robot/commands/ExampleCommand.java
This is the drivetrain and localization core. It:
- loads YAGSL config from
src/main/deploy/swerve - builds the
SwerveDrivewithSwerveParser - loads the 2026 AprilTag field layout
- publishes a
Field2dobject - exposes field-oriented drive helpers
- configures PathPlanner
AutoBuilder - returns
PathPlannerAutoinstances by name - fuses Limelight pose estimates into odometry during
periodic() - provides
alignToOffset(), which pathfinds to a tag-relative field pose using MegaTag2 estimates
Current limitations:
- vision fusion only checks
tagCount > 0 periodic()prints aggressively every cycle, which will spam logs on real hardware
This is a thin cache over LimelightHelpers. It updates:
- target valid flag
- closest AprilTag ID
txty
It keeps command code simple by exposing cached getters instead of raw NetworkTables calls.
The file name is lowercase, but the public class is Intake. The subsystem owns:
- roller SparkMax, CAN ID
9 - extension SparkMax, CAN ID
10
It uses a small PeriodicIO struct to stage demand/current values and exposes percent-output setters plus stop helpers. The case mismatch is a portability risk on case-sensitive filesystems.
Indexer follows the same pattern as Intake:
- one SparkMax indexer motor, CAN ID
11 PeriodicIOstate holder- percent-output control with a simple
stop()
Turret is the most feature-rich mechanism subsystem. It manages:
- flywheel leader, CAN ID
14 - flywheel follower, CAN ID
15 - hood motor, CAN ID
16 - turret rotation motor, CAN ID
17 - encoder-backed hood and rotation feedback
- PID-based hood and rotation control modes
- soft limits for hood and rotation travel
- SmartDashboard telemetry
This is the subsystem used by both manual superstructure commands and the automated shooting commands.
This is unused WPILib starter code.
src/main/java/frc/robot/LimelightHelpers.java is the large static utility that wraps Limelight NetworkTables and pose-estimation APIs. The current codebase uses it for:
getTV,getTX,getTYgetFiducialIDgetBotPose_TargetSpacegetBotPoseEstimate_wpiBluegetBotPoseEstimate_wpiBlue_MegaTag2
VisionSubsystem uses it to cache target data, and SwerveSubsystem uses it to inject vision measurements into odometry.
RobotContainer.getAutonomousCommand() currently builds:
drivebase.getAutonomousCommand("ScoreLeftSideAuto")ShootAuto.shoot(turret, indexer, vision)
The intent is to drive a PathPlanner routine first and then run an autonomous shooting sequence.
RobotContainer defines hardcoded field targets used by shooting logic:
- blue alliance target:
(0.0, 5.5) - red alliance target:
(16.54, 5.5)
Files under src/main/deploy/pathplanner/autos:
ScoreLeftSideAuto.autoScoreRightSideAuto.autoScoreIntakeScore.autoSimple Auto.auto
Files under src/main/deploy/pathplanner/paths:
ScoreLeftSide.pathScoreRightSide.pathIntakeBack.pathIntakeToShoot.pathSimple Path.path
ScoreIntakeScore.auto is the most involved asset. It chains:
ScoreLeftSide- wait
3.0seconds IntakeBack- wait
3.0seconds IntakeToShoot
Files under src/main/deploy/swerve:
swervedrive.jsoncontrollerproperties.jsonmodules/frontleft.jsonmodules/frontright.jsonmodules/backleft.jsonmodules/backright.jsonmodules/physicalproperties.jsonmodules/pidfproperties.json
swervedrive.json defines:
pigeon2IMU on CAN ID17- four module config files
Module JSONs define the actual drivetrain hardware map:
frontleft: drive4, angle3, CANcoder21, offset31.20frontright: drive2, angle1, CANcoder22, offset59.50backleft: drive8, angle7, CANcoder24, offset100.53backright: drive6, angle5, CANcoder23, offset297.68
That mapping is what SwerveSubsystem loads through SwerveParser at runtime.
build.gradleuses theedu.wpi.first.GradleRIOplugin at2026.2.1- source and target compatibility are both Java 17
- desktop simulation is enabled
- JUnit 5 is configured for tests
- deploy copies
src/main/deployto/home/lvuser/deploy
settings.gradle points Gradle at the local WPILib Maven cache.
.wpilib/wpilib_preferences.jsonsets team5190and languagejava.vscode/launch.jsoncontains WPILib desktop and roboRIO debug targets.vscode/settings.jsonenables automatic Java build config updates and configures the WPILib unit-test environment
vendordeps/ contains JSON descriptors for:
AdvantageKitPathplannerLibPhoenix5Phoenix6REVLibReduxLibStudicaStudicaLibThriftyLibWPILibNewCommandsyagsl
src/main/java/frc/robot/Constants.java currently centralizes only a few values:
- driver controller port
0 - driver deadband
0.05 maximumSpeed = Units.feetToMeters(1)(~0.305 m/s)
Most hardware IDs and tuning values still live inside subsystem-local Constants inner classes.
src/main/java/frc/robot/
├── Main.java
├── Robot.java
├── RobotContainer.java
├── Constants.java
├── Superstructure.java
├── LimelightHelpers.java
├── commands/
│ ├── AlignTurretToTag.java
│ ├── Autos.java
│ ├── ExampleCommand.java
│ ├── ShootAuto.java
│ └── ShootOnTheMove.java
└── subsystems/
├── ExampleSubsystem.java
├── Indexer.java
├── SwerveSubsystem.java
├── Turret.java
├── VisionSubsystem.java
└── intake.java
src/main/deploy/
├── pathplanner/
│ ├── autos/
│ └── paths/
└── swerve/
├── controllerproperties.json
├── swervedrive.json
└── modules/
vendordeps/
.wpilib/
.vscode/
- Repair
ShootAuto.javaso autonomous compilation and runtime flow matchRobotContainer. - Resolve the controller-port mismatch between
Constants.javaandRobotContainer. - Verify CAN ID
17is not double-booked between the turret rotation motor and the Pigeon2. - Replace placeholder drivetrain and shooting tuning values, especially
maximumSpeed. - Remove or clearly isolate WPILib template files.
- Reduce
System.out.printlnspam inSwerveSubsystem.periodic().
The repo already has the shape of a real competition robot codebase: a command-scheduled WPILib runtime, swerve driving, Limelight-backed localization, a turret subsystem, and PathPlanner auto assets. The most mature active behavior is the swerve + ShootOnTheMove path. The main missing step is cleanup and stabilization so the autonomous and hardware configuration match the intended design.
Team 5190's 2026 robot codebase is a Java 17 WPILib command-based project built on GradleRIO, YAGSL swerve, PathPlanner autos, REV motor controllers, CTRE sensors, and Limelight AprilTag vision. The code currently centers on a swerve drivetrain, a Limelight-backed targeting stack, and a scoring superstructure made up of an intake, indexer, and turret.
src/main/java/frc/robot/Main.javaboots WPILib and startsRobot.src/main/java/frc/robot/Robot.javaowns mode transitions and runs theCommandScheduler.src/main/java/frc/robot/RobotContainer.javawires subsystems, controller bindings, default drive behavior, and autonomous selection.src/main/java/frc/robot/subsystems/contains hardware-facing code for the swerve, vision, intake, indexer, and turret.src/main/java/frc/robot/commands/contains targeting and shooting commands.src/main/deploy/pathplanner/stores.autoand.pathassets used by PathPlanner.src/main/deploy/swerve/stores the YAGSL swerve JSON configuration loaded at runtime.vendordeps/tracks external robotics libraries such as YAGSL, PathPlanner, REVLib, Phoenix 5/6, ThriftyLib, AdvantageKit, ReduxLib, and WPILib command support.
The startup path is standard WPILib. Main calls RobotBase.startRobot(Robot::new), and Robot constructs a single RobotContainer. Every scheduler tick, robotPeriodic() runs CommandScheduler.getInstance().run(), which drives all command-based behavior.
RobotContainer is the real wiring hub. It creates:
SwerveSubsystem drivebaseVisionSubsystem visionIntake intakeIndexer indexerTurret turretSuperstructure superstructure
It also defines alliance-specific scoring targets at (0.0, 5.5) for blue and (16.54, 5.5) for red, which are consumed by ShootOnTheMove.
The default drive command is a field-oriented SwerveInputStream built from the Xbox controller:
- left stick Y/X drive translation
- right stick X drives angular velocity
- 0.05 deadband from
Constants.OperatorConstants.DEADBAND - translation scaled to 80%
- alliance-relative control enabled
There is also an unused direct-angle drive stream that derives heading from the right stick X/Y pair.
The current driver bindings live in RobotContainer.configureBindings():
A: run intake roller forward at0.6B: run intake roller backward at-0.6Right Bumper: extend intake at0.2Left Bumper: retract intake at-0.2Left Trigger: runShootOnTheMove
Commented-out bindings show intended future use for indexer jogging and AprilTag-relative drive alignment. The command-based example trigger still exists, but it only points at the WPILib template subsystem and command.
SwerveSubsystem loads its hardware definition from src/main/deploy/swerve/ using new SwerveParser(directory).createSwerveDrive(...). It sets telemetry to HIGH, seeds the robot pose to (1 m, 4 m, 0 deg), loads the 2026 welded field AprilTag layout, and publishes a Field2d to SmartDashboard.
In periodic(), it asks LimelightHelpers.getBotPoseEstimate_wpiBlue("limelight") for a pose estimate. If a tag is visible, the result is fused into the swerve odometry with addVisionMeasurement(...). The subsystem also exposes:
driveFieldOriented(...)for field-relative controlsetUpPathPlanner()to configureAutoBuildergetAutonomousCommand(pathName)to return aPathPlannerAutoseesTag(tagId)for quick AprilTag checksalignToOffset(...)to pathfind to a field pose derived from a tag-relative offset
VisionSubsystem is a thin cache over Limelight data. Each loop it stores:
txhorizontal offsettyvertical offsetclosestTagIDhasTag
LimelightHelpers.java is the large helper library that wraps NetworkTables access, pose estimates, target-space transforms, and AprilTag metadata. The rest of the code treats it as the only direct API into the Limelight.
Intake controls two Spark MAX motors:
- roller motor CAN ID
9 - extension motor CAN ID
10
It stores current draw and percent demands in a PeriodicIO struct, then writes the demands in periodic().
Indexer is a single Spark MAX on CAN ID 11 and follows the same PeriodicIO pattern.
Turret manages four mechanisms:
- flywheel leader CAN ID
14 - flywheel follower CAN ID
15 - hood CAN ID
16 - rotation CAN ID
17
The flywheel runs open-loop. Hood and rotation each support manual percent output and PID position control. Soft limits clamp hood travel to 0.0..20.0 encoder rotations and turret rotation to -10.0..10.0. SmartDashboard gets live output, position, target, and at-setpoint values every loop.
Superstructure is a command factory layered on top of Intake, Indexer, and Turret. It does not own hardware itself; instead it returns reusable WPILib commands such as:
jogRollerjogExtensionjogIndexerrunFlywheeljogHoodUp/jogHoodDownsetHoodPositionjogRotationLeft/jogRotationRightsetRotationPositionautoAim
This keeps low-level motor control in the subsystems and higher-level operator actions in commands.
AlignTurretToTaguses Limelighttxas a proportional error term. If no tag is visible, it slowly spins the turret to search. It finishes once the horizontal error is under1.0degree.ShootOnTheMoveis the most advanced routine in the repository. It reads field-relative chassis speed, projects the robot's future position using a0.15 slatency term, estimates shot distance from either Limelight target-space data or odometry, looks up flywheel output from an interpolating distance table, compensates for robot motion with vector subtraction, solves for a hood pitch, and continuously commands turret rotation, hood position, and flywheel output.ShootAutois intended to align to a tag, spin up the flywheel, feed with the indexer, and stop the motors.
Robot.autonomousInit() asks RobotContainer for an autonomous command and schedules it. Right now RobotContainer.getAutonomousCommand() builds:
drivebase.getAutonomousCommand("ScoreLeftSideAuto")ShootAuto.shoot(turret, indexer, vision)
That means the default autonomous plan is: drive the ScoreLeftSideAuto PathPlanner routine, then perform an autonomous shot sequence.
The checked-in autos are:
ScoreLeftSideAuto.auto: drivesScoreLeftSide.pathScoreRightSideAuto.auto: drivesScoreRightSide.pathSimple Auto.auto: drivesSimple Path.pathScoreIntakeScore.auto: drivesScoreLeftSide, waits 3 seconds, drivesIntakeBack, waits 3 seconds, then drivesIntakeToShoot
The path files describe the actual field trajectories. ScoreLeftSide and IntakeToShoot both use a ScorePosition waypoint, while IntakeBack and IntakeToShoot also use an IntakePosition waypoint, which makes the intended cycle path easy to identify.
The YAGSL config in src/main/deploy/swerve/ defines:
- IMU: Pigeon2 on CAN ID
17 - front-left module: drive
4, angle3, CANcoder21, offset31.20 - front-right module: drive
2, angle1, CANcoder22, offset59.50 - back-left module: drive
8, angle7, CANcoder24, offset100.53 - back-right module: drive
6, angle5, CANcoder23, offset297.68
Physical and control properties are also externalized:
- robot mass
35 kg - wheel diameter
4 in - drive gear ratio
6.12 - angle gear ratio
21.42 - current limits
40 Adrive /20 Aangle - ramp rate
0.25 - heading controller gains
P=0.4,D=0.01
Keeping those values in deploy JSON means drive tuning can change without editing Java code.
Use the WPILib Java 17 toolchain. The project targets GradleRIO 2026.2.1.
Common commands:
bash gradlew build
bash gradlew test
bash gradlew simulateJava
bash gradlew deployNotes:
- the wrapper is committed without the executable bit, so
bash gradlew ...is the safest invocation .wpilib/wpilib_preferences.jsonsets the team number to5190.vscode/launch.jsonincludes both desktop and roboRIO WPILib debug targets.vscode/settings.jsonenables automatic Java build updates and configures WPILib unit-test runtime paths
This repository has several active development issues that are worth knowing before building or deploying:
ShootAuto.javais incomplete as committed: it referencesvisionwithout accepting it in the method signature, misspellswithTimeout, and is missing the closing syntax needed to compile cleanly.RobotContainercreates the Xbox controller on port1, butConstants.OperatorConstants.kDriverControllerPortis0.Turret.Constants.kRotationIdand the Pigeon2 IMU inswervedrive.jsonboth use CAN ID17, which is a hardware conflict if both devices are present on the same bus.src/main/java/frc/robot/subsystems/intake.javadeclarespublic class Intake; that case mismatch can break builds on case-sensitive filesystems.Constants.maximumSpeedis set toUnits.feetToMeters(1), which is only about0.3048 m/sand likely a placeholder rather than a final competition speed.SwerveSubsystem.periodic()prints pose and vision data every scheduler loop, which will flood logs during runtime.ExampleSubsystem,ExampleCommand, andAutosare still WPILib template leftovers and should not be mistaken for production robot behavior.
The codebase already has a clear architecture: Robot runs WPILib, RobotContainer wires the machine together, the subsystems own motors and sensors, and the commands compose those pieces into drive, alignment, and shooting behavior. The most developed systems today are the YAGSL swerve stack, the Limelight-assisted targeting path, and the intake/indexer/turret superstructure around scoring. The main work left is hardening the autonomous shot path, cleaning up placeholder code, and reconciling the configuration mismatches called out above.