Skip to main content
Get up and running with WPILib in minutes. This guide will walk you through creating a basic robot program that runs on your roboRIO.

Understanding the robot lifecycle

WPILib robot programs follow a specific lifecycle with distinct modes:
1

Robot initialization

Called once when the robot first starts up. Use this for one-time setup like configuring motors and sensors.
2

Mode initialization

Called once when entering a specific mode (autonomous, teleop, test, or disabled).
3

Periodic execution

Called every 20ms (50 times per second) during each mode. This is where your main robot logic runs.
4

Mode transitions

The robot automatically transitions between modes based on Driver Station input.

Create your first robot program

Here’s a complete basic robot program using the TimedRobot framework:
package frc.robot;

import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.smartdashboard.SendableChooser;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;

/**
 * The methods in this class are called automatically corresponding to each mode.
 * TimedRobot runs a 20ms loop (50Hz) by default.
 */
public class Robot extends TimedRobot {
  private static final String kDefaultAuto = "Default";
  private static final String kCustomAuto = "My Auto";
  private String m_autoSelected;
  private final SendableChooser<String> m_chooser = new SendableChooser<>();

  /**
   * Called when the robot is first started up.
   * Use this for initialization code.
   */
  public Robot() {
    m_chooser.setDefaultOption("Default Auto", kDefaultAuto);
    m_chooser.addOption("My Auto", kCustomAuto);
    SmartDashboard.putData("Auto choices", m_chooser);
  }

  /**
   * Called every 20 ms, no matter the mode.
   * Runs after mode-specific periodic functions.
   */
  @Override
  public void robotPeriodic() {}

  /**
   * Called once when autonomous is enabled.
   */
  @Override
  public void autonomousInit() {
    m_autoSelected = m_chooser.getSelected();
    System.out.println("Auto selected: " + m_autoSelected);
  }

  /**
   * Called periodically during autonomous (every 20ms).
   */
  @Override
  public void autonomousPeriodic() {
    switch (m_autoSelected) {
      case kCustomAuto:
        // Put custom auto code here
        break;
      case kDefaultAuto:
      default:
        // Put default auto code here
        break;
    }
  }

  /**
   * Called once when teleop is enabled.
   */
  @Override
  public void teleopInit() {}

  /**
   * Called periodically during teleop (every 20ms).
   */
  @Override
  public void teleopPeriodic() {}

  /**
   * Called once when the robot is disabled.
   */
  @Override
  public void disabledInit() {}

  /**
   * Called periodically when disabled.
   */
  @Override
  public void disabledPeriodic() {}

  /**
   * Called once when test mode is enabled.
   */
  @Override
  public void testInit() {}

  /**
   * Called periodically during test mode.
   */
  @Override
  public void testPeriodic() {}

  /**
   * Called once when the robot is first started in simulation.
   */
  @Override
  public void simulationInit() {}

  /**
   * Called periodically in simulation.
   */
  @Override
  public void simulationPeriodic() {}
}
The TimedRobot framework automatically calls your periodic methods every 20ms (50Hz). This timing is handled by the framework - you just implement the methods.

Running in simulation

Test your robot program without hardware using WPILib’s simulation framework:
  1. Open the Command Palette (Ctrl+Shift+P / Cmd+Shift+P)
  2. Type “WPILib: Simulate Robot Code”
  3. Select your robot project
  4. Choose “Sim GUI” to open the simulation interface
The simulation GUI provides:
  • Virtual joysticks and driver station controls
  • Hardware simulation for motors, sensors, and pneumatics
  • NetworkTables viewer for debugging
  • Real-time robot state visualization

Adding hardware control

Expand your robot program to control motors and read sensors:
import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;
import edu.wpi.first.wpilibj.Joystick;

public class Robot extends TimedRobot {
  // Create motor controller on PWM port 0
  private PWMSparkMax m_motor = new PWMSparkMax(0);
  
  // Create joystick on USB port 0
  private Joystick m_joystick = new Joystick(0);

  @Override
  public void teleopPeriodic() {
    // Set motor speed from joystick Y-axis
    double speed = -m_joystick.getY(); // Invert Y-axis
    m_motor.set(speed);
  }

  @Override
  public void disabledInit() {
    // Stop motor when disabled
    m_motor.set(0);
  }
}

Best practices

Initialize once

Put initialization code in constructors or init methods, not periodic methods

Keep periodic fast

Periodic methods run every 20ms. Avoid blocking operations or long calculations

Use simulation

Test your code in simulation before deploying to hardware

Log data

Use SmartDashboard or DataLog to debug and tune your robot

Next steps

Now that you have a basic robot program running, explore these topics:

Motor control

Learn about different motor controllers and control modes

Sensors

Read encoders, gyros, and other sensors for feedback

Command-based programming

Structure complex robot programs with commands and subsystems

Vision processing

Use cameras and AprilTags for autonomous targeting

Build docs developers (and LLMs) love