Skip to content

CrevolutionRoboticsProgramming/2026RobotCode-PUBLIC

Repository files navigation

Vulcan — Crevolution Robotics (Team 2851) 2026 Robot Code

Vulcan is Crevolution Robotics' 2026 FRC competition robot. Built on a swerve drivetrain with WPILib, CTRE Phoenix 6, PathPlanner, and PhotonVision.


Table of Contents


Project Structure

src/main/java/frc/robot/
├── Main.java                        # Entry point
├── Robot.java                       # TimedRobot lifecycle
├── RobotContainer.java              # Subsystem wiring & button bindings
├── RobotCommands.java               # Composed command sequences
├── Telemetry.java                   # Drivetrain NetworkTable publishing
├── ShiftHelpers.java                # 2026 game shift-period logic
├── drivetrain/
│   └── CommandSwerveDrivetrain.java # CTRE swerve wrapper
├── generated/
│   └── TunerConstants.java          # Auto-generated swerve config (Tuner X)
├── intake/
│   ├── Intake.java                  # Slide + roller subsystem
│   ├── IntakeCommands.java          # Simple intake command factories
│   ├── IntakeConfig.java            # IDs, PID gains, limits
│   ├── CompressIntakeCommand.java   # Double-oscillation compression sequence
│   └── HomeIntakeCommand.java       # Limit-switch homing
├── shooter/
│   ├── Shooter.java                 # Flywheel subsystem + SOTM math
│   ├── ShooterCommands.java         # Aim-and-shoot / stop factories
│   ├── ShooterConfig.java           # IDs, PID gains, distance→RPM table
│   └── ShooterTuningBench.java      # Manual RPM tuning command
├── treadmill/
│   ├── Treadmill.java               # Belt conveyor subsystem
│   ├── TreadmillCommands.java       # State command factories
│   └── TreadmillConfig.java         # Motor ID & voltage constants
├── indexer/
│   ├── Indexer.java                 # Two-stage indexer subsystem
│   ├── IndexerCommands.java         # State command factories
│   └── IndexerConfig.java           # Motor IDs & voltage constants
├── climber/
│   ├── Climber.java                 # Hook actuator subsystem
│   ├── ClimberCommands.java         # Climb command factory
│   └── ClimberConfig.java           # IDs, Motion Magic gains, targets
└── vision/
    ├── PhotonVisionSystem.java      # 4-camera pose estimation
    ├── VisionCommands.java          # Teleop/auton auto-aim commands
    ├── DriveToPoseCommand.java      # PID drive-to-pose command
    ├── TeleopAxisLockedDrive.java   # Climb-approach drive (X-axis locked)
    ├── ApriltagTarget.java          # AprilTag ID → 3D offset mapping
    └── LoggableRobotPose.java       # Pose3d + timestamp wrapper

Subsystems

Drivetrain

Class: CommandSwerveDrivetrain (extends CTRE TunerSwerveDrivetrain)
Config: TunerConstants (auto-generated by Tuner X — do not hand-edit)

Swerve drivetrain using CTRE Phoenix 6. All constants (wheel offsets, encoder IDs, PID gains) live in TunerConstants. The robot runs in field-centric mode by default.

  • Max teleop speed: 65% of kSpeedAt12Volts
  • Max angular rate: 0.8 rotations/second
  • Odometry is fused with PhotonVision AprilTag estimates each loop

Intake

Class: Intake
Config: IntakeConfig

Controls two mechanisms:

Mechanism Control
Slide Motion Magic (position)
Rollers Voltage open-loop; motor 2 is a configured Follower (opposed)

Slide States:

State Description
RETRACTED Fully retracted home position
EXTENDED Fully deployed position
CUSTOM Arbitrary position (used by CompressIntakeCommand)
HOMING Applies kHomingVolts until limit switch triggers

Roller States: IDLE, INTAKE, EJECT

The limit switch at home zeroes the encoder every loop it remains pressed, providing drift-free position after homing. Within 0.025 rotations of target, a gravity feedforward holds position instead of running Motion Magic.

CompressIntakeCommand runs a 7-state double-oscillation sequence to seat a game piece: WAIT → COMPRESS_ONE_THIRD → EXTEND_FIRST → COMPRESS_TWO_THIRDS → EXTEND_SECOND → COMPRESS_FULL → DONE


Treadmill

Class: Treadmill
Config: TreadmillConfig

Belt conveyor that moves game pieces between the intake and indexer. Runs on the CANivore bus.

State Voltage
IDLE kTreadmillIdleVolts
INTAKE kTreadmillInVolts
EJECT kTreadmillEjectVolts

Indexer

Class: Indexer
Config: IndexerConfig

Two-stage indexer with separate motors for initial staging and final feeding. Uses voltage open-loop control.

State Description
IDLE Both motors stopped
INTAKE_BOTH Both stages run forward (used for feeding the shooter)
QUEUE_TO_FINAL Moves piece from initial stage to final stage
FEED_SHOOTER Final stage only — direct feed into flywheel
EJECT Both stages reversed

Shooter

Class: Shooter
Config: ShooterConfig

Four-motor 2x2 flywheel: Motor 1 is the leader, Motor 2 follows aligned, Motors 3 and 4 follow opposed. Uses VelocityVoltage closed-loop control (Phoenix 6 Slot 0).

Shooter States:

State Behavior
IDLE Flywheels coast to zero
SHOOTING Runs SOTM math and sets RPM from the distance→RPM table
TUNING Uses manually-set RPM from ShooterTuningBench
HOMING Reserved for hood homing (hood hardware not installed)

Shoot-on-the-Move (SOTM) Kinematics:

Each loop, the shooter:

  1. Gets the robot's velocity from the drivetrain odometry.
  2. Applies a 5-loop moving-average filter to smooth velocity noise.
  3. Converts to field-relative velocity components.
  4. Looks up time-of-flight for the current static distance.
  5. Computes a "virtual target" = rawTarget − (velocity × ToF).
  6. Uses the virtual distance for RPM lookup and the virtual angle as mTargetHeading.

A non-linear angular correction is also applied at extreme side angles to compensate for hub geometry (cubic curve, max kMaxHeadingOffsetDegrees = 5°).

Zone logic: The shooter automatically selects between a scoring hub target (when the robot is within BLUE/RED_SCORING_*_X) and passing targets (mid-field, high/low selected by robot Y position relative to field center).

Distance → RPM table (kShooterMapData in ShooterConfig):

Distance (m) RPM ToF (s)
1.900 3022 0.850
2.135 3022 0.870
2.282 3022 0.890
2.619 3339 0.940
2.865 3460 0.970
3.076 3486 1.000
3.585 3655 1.090
3.614 3996 1.100
3.850 4109 1.120
4.100 4395 1.150

Values are linearly interpolated. Points above/below the table are clamped to the nearest endpoint.


Climber

Class: Climber
Config: ClimberConfig

Hook actuator using Motion Magic with Elevator_Static gravity feedforward. Targets are defined as rotations in ClimberConfig and correspond to retracted and climbed positions.


Vision

Class: PhotonVisionSystem

Four cameras running PhotonVision for AprilTag-based odometry: FL (Front Left), FR (Front Right), BL (Back Left), BR (Back Right). Camera-to-robot transforms are defined as Transform3d constants in PhotonVisionSystem.

Pose filtering rules:

  • Multi-tag solves are always accepted.
  • Single-tag solves are accepted only when pose ambiguity < 0.2 and tag distance < 4.0 m.

Each loop, hub heading and distance are recalculated from odometry pose and field geometry — no camera visibility is required for the shooter to function.

Accepted pose estimates are forwarded to RobotContainer via a Consumer<LoggableRobotPose> callback, which feeds them into swerve odometry with addVisionMeasurement.

Other vision classes:

  • VisionCommandsteleopAlign and autonAutoAim using tangential velocity feedforward
  • DriveToPoseCommand — PID drive-to-pose; translates slower when heading error > 90°
  • TeleopAxisLockedDrive — Climb-approach command that locks the X axis while allowing Y strafe, with alliance-aware hard limits

Core Classes

RobotContainer

File: RobotContainer.java

The root wiring class. Instantiates all subsystem singletons, registers PathPlanner named commands, builds the autonomous chooser, and binds every button.

Key fields:

  • MaxSpeed — 65% of kSpeedAt12Volts
  • MaxAngularRate — 0.8 rot/s
  • autoChooserSendableChooser<Command> shown on SmartDashboard
  • debugFieldField2d for simulation pose visualization

Climb target poses (used by getClosestClimbTarget()):

Alliance Position Pose
Blue HIGH (1.183, 4.728) facing 0°
Blue LOW (0.901, 2.756) facing 180°
Red HIGH (15.653, 5.310) facing 0°
Red LOW (15.312, 3.335) facing 180°

RobotCommands

File: RobotCommands.java

Static factory class for composed command sequences. All methods return a Command.

Method Description
extendIntake() Sets slide to EXTENDED
retractIntake() Sets slide to RETRACTED
runIntakeRollers() Runs rollers at INTAKE voltage; gated to slide position ≥ 2.35 rot
runRollers() runEnd version; only runs if slide state is EXTENDED
ejectRollers() runEnd eject; only runs if slide state is EXTENDED
extendAndRunIntakeRollers() Extends, waits until deployed, then starts rollers
stopIntakeRollers() Sets rollers to IDLE
toggleIntakeRollers() Stateful toggle (on/off per press)
smartAlign(...) Teleop shoot: aims drivetrain + spins up + fires once at setpoint
autonSmartAlign(...) Auton shoot: same as above but stationary
manualFire() runEnd on Indexer INTAKE_BOTH — blind fire
indexerEject() runEnd on Indexer EJECT
treadmillRun() runEnd on Treadmill INTAKE
treadmillEject() runEnd on Treadmill EJECT
superstructureControl(...) Combined prime/fire state machine driven by trigger axes
alignToClimb(...) Retracts intake → drives to alliance-specific climb pose
performClimb() Retracts intake + runs climber in parallel
teleopClimbSlide(...) TeleopAxisLockedDrive to the nearest climb target
stopAll() Stops rollers, treadmill, indexer, and shooter simultaneously

smartAlign sequence detail:

parallel(
  1. drivetrain rotation PID toward getTargetHeading()
     + 0.15 rad/s friction feedforward when not at goal
  2. ShooterCommands.aimAndShoot()   ← spins up immediately
  3. WaitUntil(isAtSetpoint()).withTimeout(1.5s)
       .andThen( parallel( treadmillRun(), manualFire() ) )
)

ShiftHelpers

File: ShiftHelpers.java

Utility class for 2026 game shift-period logic. Determines which alliance has the current offensive turn based on match time and shift intervals. Used to adjust autonomous and teleop behavior accordingly.


Telemetry

File: Telemetry.java

Publishes drivetrain state to NetworkTables each loop via telemeterize(SwerveDriveState). Logs:

  • Robot pose (struct)
  • Module states (speeds, angles)
  • Module targets
  • Chassis speeds
  • Odometry frequency

Registered with drivetrain.registerTelemetry(logger::telemeterize) in RobotContainer.


Joystick Controls

Both controllers are Xbox controllers (WPILib CommandXboxController).

Driver Controller (Port 0)

Input Action
Left Stick (X/Y) Field-centric translation
Right Stick (X) Rotation
Start Reset gyro heading (Blue = 0°, Red = 180°)
Right Bumper (hold) smartAlign — auto-aim drivetrain + spin up + fire when ready
Right Trigger (hold) Drive at 70% speed (precision mode)
Left Trigger (hold) Run intake rollers (only while slide is extended)
Left Bumper (hold) Shooter tuning bench (TUNING state)
A Run CompressIntakeCommand (double-oscillation compress sequence)
B Extend intake slide
X Retract intake slide
Y Home intake (drive to limit switch, zero encoder)

Operator Controller (Port 1)

Input Action
Left Trigger (hold) Eject intake rollers
Right Trigger (hold) Run intake rollers
Left Bumper Retract intake slide
Right Bumper Extend intake slide
A (hold) Run treadmill (INTAKE direction)
B (hold) Manual fire — runs indexer INTAKE_BOTH (blind fire)
X (hold) Indexer eject
Y (hold) Treadmill eject
D-Pad Up Home intake (limit-switch homing)
D-Pad Right Bump tuning RPM up (+25 RPM per press)
D-Pad Left Bump tuning RPM down (−25 RPM per press)

Tuning workflow: Hold Driver Left Bumper to activate ShooterTuningBench. Use Operator D-Pad Right/Left to adjust target RPM in 25 RPM steps while watching TuningBench/TargetRPM on SmartDashboard. Release the bumper to return to normal SOTM operation.


Autonomous

Autonomous routines are built with PathPlanner and selected via SendableChooser on SmartDashboard (Auto Selector).

Available auto options (all Left-side routines also have mirrored Right-side variants):

Chooser Name Description
L-1114 1114-style 3-piece auto
L-BeesSwoop Bees swoop path
L-BeesSwoopInverted Inverted swoop variant
L-BeesSwoopLong Extended swoop
L-DoubleSwoop Two-swoop sequence
L-DoubleSweep Two-sweep sequence
L-WaitDip Wait then dip path

Named commands registered with PathPlanner:

Name Command
AutoSmartAlign RobotCommands.autonSmartAlign(drivetrain)
IntakeExtend Extend intake slide
IntakeExtendAndRunRollers Extend then start rollers
IntakeRetract Retract intake slide
IntakeRunRollers Start rollers (position-gated)
IntakeStopRollers Stop rollers

Tuning & Configuration

File Contents
TunerConstants.java Swerve module offsets, CAN IDs, PID gains — regenerate with Tuner X
IntakeConfig.java Slide motor ID, roller motor IDs, gear ratio, PID/MM gains, soft limits, voltages
ShooterConfig.java Motor IDs, velocity PID gains, distance→RPM interpolation table, heading correction constants
TreadmillConfig.java Motor ID, voltage constants, current limit
IndexerConfig.java Motor IDs, voltage constants
ClimberConfig.java Motor ID, Motion Magic gains, target rotation positions

Adding a new shooter map point:
Edit kShooterMapData in ShooterConfig. Format is {distance_meters, rpm, time_of_flight_seconds}. The third column is optional but required for SOTM correction to be accurate at that distance. Points are automatically interpolated — no code changes needed elsewhere.

Swerve calibration:
Re-run Tuner X and regenerate TunerConstants.java whenever modules are re-zeroed or gearboxes are swapped. Do not hand-edit that file.

About

Vulcan -- Crevolution Robotics (Team 2851) 2026 FRC Robot Code

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages