GradleRIO Java command-based project for a CTRE swerve + vision-assisted shooter robot (2024-style game logic: speaker, amp, pass, intake cycles). Built on a TalonFX swerve template, extended with Limelight aiming, lookup-table shooting, and PathPlanner autos.
Stack: WPILib 2024 · Phoenix 6 · PathPlannerLib · REV · PhotonLib (Limelight helpers) · Playing With Fusion TOF (transfer sensing)
flowchart TB
subgraph inputs["Inputs"]
JOY["Joystick (port 0)\ndrive axes"]
DRV["PS5 Driver (port 0)"]
OPR["PS5 Operator (port 1)"]
LL["Limelight\n(speaker pipeline)"]
ILL["Intake Limelight\n(note pipeline)"]
end
subgraph core["RobotContainer"]
RC[Bindings + NamedCommands]
AC[AutoChooser]
end
subgraph drive["Drivetrain"]
SW[Swerve]
TS[TeleopSwerve]
end
subgraph mech["Mechanisms"]
INT[IntakeSubsystem]
TR[TransferSubsystem\ngate + TOF]
ARM[ArmSubsystem\nMotion Magic]
SH[ShooterSubsystem\ndual TalonFX velocity]
end
subgraph vision["Vision Shoot"]
VLT[VisionLookUpTable]
LSA[LookUpShootAndArm]
end
JOY --> TS
DRV --> RC
OPR --> RC
RC --> TS
RC --> INT & TR & ARM & SH
LL --> LSA
LL --> TS
ILL --> RC
VLT --> LSA
SW --> TS
AC --> SW
TR --> SH
INT --> TR
ARM --> SH
| Subsystem | Hardware | Role |
|---|---|---|
Swerve |
Pigeon2 + 4× TalonFX modules | Field-centric drive, odometry, PathPlanner AutoBuilder holonomic follower |
IntakeSubsystem |
TalonFX | Floor intake roller |
TransferSubsystem |
TalonFX + servo gate + TOF | Moves notes through indexer; openGate() / closeGate() for shot timing |
ArmSubsystem |
TalonFX (Motion Magic) | Aim angle presets (ScoringEnum) + dynamic vision angle |
ShooterSubsystem |
Dual TalonFX | Velocity-controlled flywheels; asymmetric L/R speeds supported |
LimelightSubsystem |
Limelight | Speaker targeting (tx, ty, distance) |
IntakeLimelightSubsystem |
Limelight | Note-relative heading for OverrideToNote auto |
Default commands (from RobotContainer):
- Swerve →
TeleopSwerve - Intake → hold at 0
- Shooter →
stop() - Arm →
INTAKEpreset - Transfer →
transferDefault()
Drive sticks come from a Joystick on port 0 (mapped to PS5 axis IDs). Two PS5 controllers on ports 0 and 1 handle gamepiece and shoot actions. Either driver or operator can trigger shared actions via Trigger.or().
flowchart LR
subgraph driver["Driver PS5 + Joystick"]
D1["Left stick → translate/strafe"]
D2["Right stick → rotate\n(magnitude + atan2 blend)"]
D3["R2 → intake forward"]
D4["L2 → intake reverse"]
D5["R1 → open gate + feed"]
D6["L1 → amp shoot ramp"]
D7["△ hold → vision arm + LookUpShoot"]
D8["POV↑ → manual flywheel 3000"]
D9["POV↓ → PASS arm preset"]
D10["Options (joystick) → zero gyro"]
end
subgraph operator["Operator PS5"]
O1["R2 → intake forward"]
O2["L2 → intake reverse"]
O3["R1 → GetReady SOURCE"]
O4["○ → GetReady CENTER"]
O5["□ → GetReady AMP"]
O6["L1 → amp shoot ramp"]
O7["△ → AMP arm preset"]
O8["POV↓ → INTAKE preset"]
O9["Touchpad hold → SPEAKER + SmartShoot"]
end
TeleopSwerve is the default drive command. Besides manual translation/rotation it:
- Applies squared input scaling and deadband (
SquaredInput) - Supports heading hold via operator buttons passed into the constructor (
R1,○,□,△) — PID locks field heading while translating - Integrates Limelight-assisted rotation when the triangle trigger is held
- Can run in robot-centric mode when
PSis held (driver)
| Command | What it does |
|---|---|
Intake |
Runs intake + transfer forward; sets arm to INTAKE; reverses shooter slightly for dejam |
LookUpShoot |
Reads Limelight distance → VisionLookUpTable → sets flywheel speeds + feeds when ready |
ArmVision |
Sets arm angle from vision lookup (paired with LookUpShoot on △) |
GetReady |
Pre-spins flywheels + arm for pass positions (1=source, 2=center, 3=amp) |
SmartShoot |
Fixed-speed speaker shot with transfer feed |
AutoRoutines.ampFlywheelRampThenShoot |
Amp shot sequence: spin up → open gate → feed |
Constants.getLookupTable() defines distance → (arm angle, left RPM, right RPM) knots. VisionLookUpTable binary-searches and interpolates. Used by LookUpShoot, LookUpShootAndArm, ShootSpeedUpNoArm, and ArmVision.
sequenceDiagram
participant SD as SmartDashboard
participant AB as AutoBuilder
participant PP as .auto + .path files
participant SW as Swerve
participant NC as NamedCommands
SD->>AB: autoChooser.getSelected()
AB->>PP: load auto JSON
loop each path segment
AB->>SW: holonomic path follow
end
loop each named event
AB->>NC: run registered command
NC->>SW: FixHeading / TurnToAngle / OverrideToNote
NC->>SH: limeShot / ShooterSpeedUp / shootRampUp
NC->>INT: Intake / QuickIntake / IntakeStop
end
Autos live in src/main/deploy/pathplanner/autos/. Paths in src/main/deploy/pathplanner/paths/. Select on the Auto Chooser widget.
| Auto | Notes |
|---|---|
5Note.auto / 5Note-Mathew.auto |
Multi-cycle with limeShot, intake deadlines, heading fixes |
AA-6Note.auto |
6-note style path; folder AA-6Note |
state_source.auto |
Source-side state auto; folder state_source |
SourceSideAuto.auto |
Source intake + TurnToAngle + limeShot |
v4a 4 note.auto |
4-note speaker cycle |
Speaker1.auto |
Short speaker test |
FullFarNoteAuto.auto |
Far-side note paths + limeShot |
LimeShotTest.auto |
Intake + OverrideToNote + limeShot |
BasicAuto.auto / TestAuto.auto |
Path-only / smoke tests |
These must match string names in .auto / event markers in .path files.
| Name | Implementation summary |
|---|---|
ResetAutoGyro |
s_Swerve.resetAutoHeading() |
Intake |
Close gate → intake + transfer run |
QuickIntake |
Short aggressive intake burst |
IntakeStop |
Stop intake → brief reverse transfer pulse |
FixHeading |
AutoRotateToSpeaker (Limelight snap to speaker) |
TurnToAngle |
PID rotate toward Limelight target |
limeShot |
Full vision shot: stop intake → backfeed → open gate → LookUpShootAndArm → arm to auto-intake |
limeShotOnly |
Vision shot without pre-roll sequence |
ShooterSpeedUp |
Spin flywheels from lookup (no arm move) |
shootRampUp |
Fixed-speed ramp (ShooterAndArmRampUp) — used in path events |
OverrideToNote |
Rotate to intake Limelight note bearing |
flowchart TD
A[IntakeStop] --> B[Transfer backfeed -0.25]
B --> C[Transfer stop]
C --> D[openGate]
D --> E[LookUpShootAndArm\nLimelight → lookup table]
E --> F[armSetIntake preset]
src/main/java/frc/robot/
├── Robot.java # TimedRobot + CANdle init
├── RobotContainer.java # Subsystems, bindings, NamedCommands, auto chooser
├── Constants.java # Swerve + mechanism IDs + shooter lookup table
├── commands/
│ ├── TeleopSwerve.java # Default drive + heading assist
│ ├── AutoRoutines.java # Shared auto/teleop sequences
│ ├── LookUpShoot*.java # Vision shooting
│ └── ...
└── subsystems/
src/main/deploy/pathplanner/
├── autos/*.auto
├── paths/*.path
├── settings.json
└── navgrid.json
./gradlew build # compile + run checks
./gradlew deploy # deploy jar + src/main/deploy to roboRIODeploy directory on the Rio: /home/lvuser/deploy (PathPlanner files included).
Tuning entry points:
- Swerve geometry/PIDs →
Constants.Swerve - Arm presets →
ArmSubsystem.ScoringEnum+setArmPosition() - Shot tuning →
Constants.getLookupTable()presets - Auto paths → PathPlanner GUI → commit updated
.path/.auto
Robot.java configures a CTRE CANdle (Constants.CANdLEID) for status indication. Not driven by a subsystem — animations triggered from mechanism code as needed.
| Vendordep | Used for |
|---|---|
| Phoenix 6 | Swerve, arm, shooter, intake, transfer |
| Phoenix 5 | CANdle LEDs |
| PathPlannerLib | Autos + holonomic following |
| REVLib | (available; mechanism code primarily CTRE) |
| photonlib | PhotonUtils helpers in Limelight code paths |
| playingwithfusion2024 | TOF on transfer |
| Preset | Typical use |
|---|---|
INTAKE |
Floor pickup |
SPEAKER / FARSPEAKER |
Fixed speaker shots |
AMP |
Amp scoring angle |
PASS |
Pass shot |
AUTOINTAKE |
Post-shot stow |
AUTOSHOOT* |
Auto aim variants |
- Branch from
main - Run
./gradlew compileJavabefore PR - If you add PathPlanner named events, register the command in
RobotContainerbeforeAutoBuilder.buildAutoChooser() - Keep lookup-table distances in meters from bumper to target