Skip to main content

Overview

WPILib provides a structured framework for writing robot code. The most common approach is using the TimedRobot class, which provides periodic callback methods for different robot states.

TimedRobot Class

The TimedRobot class is the foundation of most WPILib robot programs. It runs periodic functions at a fixed rate (default: 20ms / 50Hz).

Java Implementation

Source: wpilibj/src/main/java/edu/wpi/first/wpilibj/TimedRobot.java:18
package frc.robot;

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

/**
 * The TimedRobot class is intended to be subclassed by a user creating a robot program.
 * 
 * Periodic functions are called on an interval by a Notifier instance.
 */
public class Robot extends TimedRobot {
  // Default period is 20ms (0.02 seconds)
  public static final double kDefaultPeriod = 0.02;

  /**
   * Robot initialization - runs once when robot starts
   */
  @Override
  public void robotInit() {
    System.out.println("Robot initialized");
  }

  /**
   * Called every ~20ms regardless of mode
   */
  @Override
  public void robotPeriodic() {
    // This runs in all modes
  }

  /**
   * Autonomous initialization - runs once when autonomous starts
   */
  @Override
  public void autonomousInit() {
    System.out.println("Autonomous started");
  }

  /**
   * Autonomous periodic - runs every ~20ms during autonomous
   */
  @Override
  public void autonomousPeriodic() {
    // Autonomous control code here
  }

  /**
   * Teleop initialization - runs once when teleop starts
   */
  @Override
  public void teleopInit() {
    System.out.println("Teleop started");
  }

  /**
   * Teleop periodic - runs every ~20ms during teleop
   */
  @Override
  public void teleopPeriodic() {
    // Driver control code here
  }

  /**
   * Test initialization - runs once when test mode starts
   */
  @Override
  public void testInit() {
  }

  /**
   * Test periodic - runs every ~20ms during test mode
   */
  @Override
  public void testPeriodic() {
  }

  /**
   * Simulation initialization - runs once in simulation
   */
  @Override
  public void simulationInit() {
  }

  /**
   * Simulation periodic - runs every ~20ms in simulation
   */
  @Override
  public void simulationPeriodic() {
  }
}

Custom Loop Period

You can customize the loop period when constructing the robot:
// Custom period: 10ms (100Hz)
public Robot() {
  super(0.01);  // 10ms period
}

// Or using units
import static edu.wpi.first.units.Units.Seconds;
import edu.wpi.first.units.measure.Time;

public Robot() {
  super(Time.ofSeconds(0.01));
}

Periodic Callbacks

Source: wpilibj/src/main/java/edu/wpi/first/wpilibj/TimedRobot.java:203 You can add custom periodic callbacks that run at different rates:
@Override
public void robotInit() {
  // Run sensor update every 50ms
  addPeriodic(this::updateSensors, 0.05);
  
  // Run vision processing every 100ms with 10ms offset
  addPeriodic(this::processVision, 0.1, 0.01);
}

private void updateSensors() {
  // Read sensor values
}

private void processVision() {
  // Process camera frames
}

Main Entry Point

package frc.robot;

import edu.wpi.first.wpilibj.RobotBase;

public final class Main {
  private Main() {}

  public static void main(String... args) {
    RobotBase.startRobot(Robot::new);
  }
}

Complete Example

Here’s a complete robot program that drives with a joystick:
package frc.robot;

import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;

public class Robot extends TimedRobot {
  private DifferentialDrive m_robotDrive;
  private Joystick m_driverController;

  @Override
  public void robotInit() {
    // Initialize motor controllers
    PWMSparkMax leftMotor = new PWMSparkMax(0);
    PWMSparkMax rightMotor = new PWMSparkMax(1);
    
    // Create drive base
    m_robotDrive = new DifferentialDrive(leftMotor, rightMotor);
    
    // Initialize joystick
    m_driverController = new Joystick(0);
  }

  @Override
  public void teleopPeriodic() {
    // Arcade drive with joystick
    m_robotDrive.arcadeDrive(
      -m_driverController.getY(),
      m_driverController.getX()
    );
  }

  @Override
  public void disabledInit() {
    // Stop motors when disabled
    m_robotDrive.stopMotor();
  }
}

Loop Timing

Source: wpilibj/src/main/java/edu/wpi/first/wpilibj/TimedRobot.java:190

Get Loop Start Time

Access the precise start time of the current loop iteration:
@Override
public void teleopPeriodic() {
  long loopStartTime = getLoopStartTime();
  // Time is in microseconds, same base as Timer.getFPGATimestamp()
}

Best Practices

  • Keep periodic methods fast - They should complete in under 20ms
  • Initialize in Init methods - Don’t do heavy initialization in periodic methods
  • Use robotPeriodic sparingly - It runs in all modes, use mode-specific periodic methods when possible
  • Don’t block - Avoid loops or delays in periodic methods
  • Clean up resources - Override disabledInit() to stop motors and release resources

Next Steps

Build docs developers (and LLMs) love