Skip to content

Lesson 1.1: Project Structure

🎯 What You’ll Learn

By the end of this lesson you will be able to:

  • Describe the standard Java project folder structure used by FRC teams
  • Navigate from the project root to any robot code file
  • Explain the difference between entry point files and support files
  • Locate subsystems, commands, and constants in the project
  • Apply the Code Reading Framework to a file you haven’t seen before

The Big Picture: How Java Projects Are Organized

Every FRC robot project follows the same folder structure. This isn’t random β€” it’s a convention that every Java project uses, and once you learn it, you can navigate any team’s code.

Here’s what the top level looks like:

Drive2026FBI/
β”œβ”€β”€ src/
β”‚ └── main/
β”‚ β”œβ”€β”€ java/ ← All the Java source code lives here
β”‚ β”‚ └── frc/
β”‚ β”‚ └── robot/ ← YOUR robot code
β”‚ └── deploy/ ← Files deployed to the roboRIO (paths, configs)
β”œβ”€β”€ vendordeps/ ← Third-party library configs (CTRE, REV, etc.)
β”œβ”€β”€ build.gradle ← Build script (like a recipe for compiling)
└── ...

The key path to remember is:

src/main/java/frc/robot/ β€” this is where all your team’s robot code lives.

Everything outside that path is either build configuration, library setup, or deploy files. You’ll rarely need to touch those.


What is the key path where all your team's robot code lives?


Inside frc/robot/ β€” The Files That Matter

Let’s zoom into the folder where all the action happens. Open the robot code folder on GitHub (or in your IDE) and you’ll see something like this:

frc/robot/
β”œβ”€β”€ commands/ ← Command classes (robot behaviors)
β”‚ └── AutoShootCommand.java
β”œβ”€β”€ generated/ ← Auto-generated code (DO NOT EDIT)
β”‚ └── TunerConstants.java
β”œβ”€β”€ subsystems/ ← Subsystem classes (hardware control)
β”‚ β”œβ”€β”€ ClimberSubsystem.java
β”‚ β”œβ”€β”€ CommandSwerveDrivetrain.java
β”‚ β”œβ”€β”€ IntakeSubsystem.java
β”‚ β”œβ”€β”€ ShooterSubsystem.java
β”‚ └── TurretSubsystem.java
β”œβ”€β”€ Constants.java ← All configuration values (CAN IDs, speeds, etc.)
β”œβ”€β”€ LimelightHelpers.java ← Vision camera helper utilities
β”œβ”€β”€ Main.java ← Program entry point (don't touch)
β”œβ”€β”€ Robot.java ← Robot lifecycle manager
β”œβ”€β”€ RobotContainer.java ← Wires everything together
β”œβ”€β”€ Telemetry.java ← Dashboard/logging data publisher
└── TrajectoryCalculations.java ← Math for shot trajectories

That’s a lot of files! But they fall into clear categories. Let’s break them down.


Entry Point Files vs. Support Files

Not all files are created equal. Some are entry points that the WPILib framework calls automatically, and others are support files that get used by those entry points.

Entry Point Files (The Core Four)

These four files form the backbone of every FRC robot program:

FileRoleDo You Edit It?
Main.javaStarts the program β€” calls RobotBase.startRobot()Almost never
Robot.javaManages the robot lifecycle (init, periodic, disabled)Rarely
RobotContainer.javaCreates subsystems, binds buttons to commandsOften
Constants.javaStores all configuration values (CAN IDs, speeds, limits)Often

Think of it this way:

  • Main.java is the ignition key β€” it starts the engine but you never modify the key itself
  • Robot.java is the engine β€” it runs the lifecycle but you rarely open the hood
  • RobotContainer.java is the dashboard β€” it’s where you wire controls to actions
  • Constants.java is the settings panel β€” it’s where you tune values

Support Files

Everything else supports the core four:

  • Subsystem files (in subsystems/) β€” each one controls a physical mechanism on the robot
  • Command files (in commands/) β€” each one defines a behavior the robot can perform
  • Helper files (Telemetry.java, LimelightHelpers.java, TrajectoryCalculations.java) β€” utilities that other files use

βœ…Checkpoint: Core Files
Without looking back, name the four core files and describe each one's role in one sentence.
  1. Main.java β€” Starts the robot program by calling RobotBase.startRobot()
  2. Robot.java β€” Manages the robot lifecycle (what happens during init, teleop, auto, disabled)
  3. RobotContainer.java β€” Creates all subsystems and binds controller buttons to commands
  4. Constants.java β€” Stores all configuration values like CAN IDs, motor speeds, and field measurements

Locating Subsystems

Subsystems are the building blocks of your robot. Each subsystem class controls one physical mechanism. They all live in the subsystems/ folder.

Your team’s robot has 5 subsystems:

SubsystemWhat It Controls
| <GitHubLink client:load path={`src/main/java/frc/robot/subsystems/IntakeSubsystem.java`} label="IntakeSubsystem" /> | Picks up game pieces from the ground using rollers and a deploy mechanism | | <GitHubLink client:load path={`src/main/java/frc/robot/subsystems/ShooterSubsystem.java`} label="ShooterSubsystem" /> | Launches notes using dual flywheels, a feeder, indexer, and adjustable hood | | <GitHubLink client:load path={`src/main/java/frc/robot/subsystems/TurretSubsystem.java`} label="TurretSubsystem" /> | Rotates the shooter left/right to aim at the hub | | <GitHubLink client:load path={`src/main/java/frc/robot/subsystems/ClimberSubsystem.java`} label="ClimberSubsystem" /> | Handles endgame climbing with elevator and servos | | <GitHubLink client:load path={`src/main/java/frc/robot/subsystems/CommandSwerveDrivetrain.java`} label="CommandSwerveDrivetrain" /> | Swerve drive system for omnidirectional movement |

Locating Commands

Commands tell the robot what to do. They use subsystems to make things happen. Your team’s commands live in two places:

  1. The commands/ folder β€” for standalone command classes like AutoShootCommand
  2. Inside RobotContainer.java β€” for inline commands defined right where buttons are bound

Most FRC teams use a mix of both. Complex behaviors (like auto-shooting) get their own file. Simple one-liners (like β€œrun the intake at 50%”) are defined inline in RobotContainer.

A teammate wrote a complex command that coordinates three subsystems during autonomous. Where should that command class live?


Locating Constants

All the β€œmagic numbers” in the robot code β€” CAN IDs, motor speeds, field positions β€” live in Constants.java.

Constants are organized into inner classes by system:

  • ShootingConstants β€” CAN IDs and settings for the shooter, turret, feeder
  • IntakeConstants β€” CAN IDs for intake rollers and deploy motors
  • ClimberConstants β€” CAN IDs for climb motors and elevator
  • FieldConstants β€” Field dimensions, zone boundaries, target positions

For example, the intake left roller motor has CAN ID 31 and the shooter left flywheel is CAN ID 21.


Where would you look to find the CAN ID for the turret motor?


πŸ” Code Reading Exercise: Telemetry.java

Time to practice the Code Reading Framework on a file you haven’t studied yet. Open Telemetry.java on GitHub or in your IDE and answer the five questions below.

Take a few minutes to read through the file before revealing the answers. Don’t worry if you don’t understand every line β€” focus on the big picture.

πŸ” Code Reading: Telemetry.java
What does this file do?
Telemetry.java publishes robot data (position, speed, swerve module states) to NetworkTables and SmartDashboard so drivers and programmers can see what the robot is doing in real time. It also logs data to a file using SignalLogger.
What subsystem or command does it belong to?
It doesn't belong to a specific subsystem or command β€” it's a helper/utility class used by the drivetrain. RobotContainer or the drivetrain subsystem calls its telemeterize() method every loop cycle.
What methods does it expose?
It exposes one main public method: telemeterize(SwerveDriveState state), which takes the current swerve drive state and publishes all the data. The constructor Telemetry(double maxSpeed) sets up the NetworkTables publishers and Mechanism2d visualizations.
What does it depend on?
It depends on CTRE Phoenix 6 (SignalLogger, SwerveDriveState), WPILib math classes (Pose2d, ChassisSpeeds, SwerveModuleState), WPILib NetworkTables for publishing data, and WPILib SmartDashboard/Mechanism2d for visual telemetry.
When does this code run?
The telemeterize() method runs every robot loop cycle (roughly every 20ms) during all modes β€” teleop, autonomous, and disabled. It's called continuously so the dashboard always shows current data.

βœ…Checkpoint: Finding Your Way Around
A teammate asks you to find the file that controls the intake rollers. Describe the exact path you'd navigate to, starting from the project root.

Starting from the project root:

  1. Open src/main/java/frc/robot/subsystems/
  2. Open IntakeSubsystem.java

The full path is src/main/java/frc/robot/subsystems/IntakeSubsystem.java. You know it’s in the subsystems/ folder because the intake is a physical mechanism (hardware control = subsystem). The file name matches the class name β€” IntakeSubsystem.


Quick Reference: Where to Find Things

I need to find…Look in…
Any robot code file{robotConfig.projectRoot}/
A subsystem (hardware control){robotConfig.projectRoot}/subsystems/
A command (robot behavior){robotConfig.projectRoot}/commands/ or inline in RobotContainer.java
CAN IDs and motor speeds{robotConfig.projectRoot}/{robotConfig.coreFiles.constants}
Button-to-command wiring{robotConfig.projectRoot}/{robotConfig.coreFiles.robotContainer}
Auto-generated swerve config{robotConfig.projectRoot}/generated/ (read only!)

What’s Next?

Now that you can navigate the project, it’s time to understand how the code runs. In Lesson 1.2: Robot Lifecycle, you’ll learn the sequence of methods that WPILib calls when the robot starts up, enters teleop, runs autonomous, and more.

In Activity 1.3: Open & Build, you’ll open the project in your IDE and run your first Gradle build to make sure everything compiles.