Unit 6 · Lesson 9

Driver Station Logs

When a robot does something unexpected in a match and comes back to the pit, the teams that diagnose it in ten minutes are the teams with logs. This lesson covers every log channel available to you — from the simple Driver Station console to structured WPILOG files — and how to use them when the pressure is on.

By the end of this lesson, you will:

  • Identify all three log severity levels and when to use each one
  • Read a Java stack trace and locate the line of code that caused a crash
  • Use DriverStation.reportError() and reportWarning() for structured, persistent messages
  • Explain what a WPILOG file is, where it's saved, and how to open it in AdvantageScope
  • Use DataLogManager to add custom variables to the structured log
  • Distinguish between the Driver Station console (live, ephemeral) and WPILOG (persistent, replayable)

The Robot Can't Speak — But It Can Write

A robot misbehaving in a match has no way to tell you what went wrong. But it has been writing to a log file the entire time. Every message, every error, every sensor value you published — all of it, timestamped, sitting on the roboRIO's storage waiting to be read.

There are two distinct logging systems you need to understand: the Driver Station console (live text messages sent to the laptop during operation) and the WPILOG file (a structured binary file recording every variable you chose to log, replayable after the match in AdvantageScope). They serve different purposes and you need both.

The Driver Station Console: Your Live Feed

The Driver Station's Messages tab shows a live stream of text log entries from the robot. Every entry has three fields: a timestamp, a severity level, and a message. Click any row below to learn what it means.

 Driver Station — Messages Tab
00:00.001 INFO Robot program starting
00:00.043 INFO CAN bus initialized. 6 devices found.
00:02.118 WARNING Arm encoder value out of expected range: 4092 (expected 0–2048)
00:04.387 WARNING Loop time of 0.035s overran the 0.020s period
00:07.902 ERROR Unhandled exception: java.lang.NullPointerException
00:07.902 ERROR   at frc.robot.subsystems.IntakeSubsystem.hasGamePiece(IntakeSubsystem.java:47)
00:07.902 ERROR   at frc.robot.commands.IntakeCommand.isFinished(IntakeCommand.java:34)
← click a log row to understand what it means

The Three Severity Levels

LevelJava MethodWhen to UseColor in DS
INFOSystem.out.println()
DriverStation.reportInfo()
Status updates, state transitions, sensor values during development. Remove temporary ones before competition.White / blue
WARNINGDriverStation.reportWarning()Non-fatal anomalies: sensor value out of range, subsystem not at expected state, unexpected timing. Leave these in competition code.Yellow / amber
ERRORDriverStation.reportError()Fatal conditions, unhandled exceptions. The DS automatically generates ERRORs for Java exceptions. Never ignore a red ERROR row.Red

Reading a Stack Trace

A stack trace is the most valuable log entry you will ever see. It is an exact crime scene report: what exception occurred, which class threw it, and the chain of method calls that led there. Click each line below to understand what it's telling you.

❌ ERROR — Unhandled exception in robot code
java.lang.NullPointerException: Cannot invoke method get() on null object   at frc.robot.subsystems.IntakeSubsystem.hasGamePiece(IntakeSubsystem.java:47)   at frc.robot.commands.IntakeCommand.isFinished(IntakeCommand.java:34)   at edu.wpi.first.wpilibj2.command.CommandScheduler.run(CommandScheduler.java:241)   at frc.robot.Robot.robotPeriodic(Robot.java:32)
← click any line of the stack trace to understand what it means
⚠️ Read from top to bottom — but investigate from the top

The stack trace reads from most-recent call (top) to oldest call (bottom). The first line from your own code (not WPILib internals) is almost always where the bug is. In the example above, that's IntakeSubsystem.java:47. Open that file, go to line 47, and look at what could be null. The WPILib lines below yours are just the framework calling your code — they're innocent.

Structured Logging with WPILOG

The DS console is good for live debugging. But it's ephemeral — messages scroll off and it only covers what happened while you were watching. WPILOG is WPILib's structured binary log format: every variable you publish to NetworkTables is automatically logged to a timestamped file on the roboRIO's filesystem, capturing the entire match for post-match replay.

Log files live in /home/lvuser/logs/ on the roboRIO and are named by date and match number. Connect after a match, use the WPILib Device Browser or SCP to download them, and open in AdvantageScope to replay every variable against a timeline.

Robot.java + subsystem — DataLog structured logging
// In robotInit() — start the log manager
DataLogManager.start();
DriverStation.startDataLog(DataLogManager.getLog());

// ─── In a subsystem ──────────────────────────────
private final DoubleLogEntry m_speedLog;
private final BooleanLogEntry m_pieceLog;

public IntakeSubsystem() {
  // Create log entries with path-style keys
  m_speedLog = new DoubleLogEntry(DataLogManager.getLog(), "/Intake/MotorSpeed");
  m_pieceLog = new BooleanLogEntry(DataLogManager.getLog(), "/Intake/HasPiece");
}

@Override
public void periodic() {
  // Write to structured log every loop
  m_speedLog.append(m_motor.get());
  m_pieceLog.append(hasGamePiece());

  // SmartDashboard still works — both systems coexist
  SmartDashboard.putNumber("Intake/MotorSpeed", m_motor.get());
}
← click a highlighted token
🔍 LRI Perspective: "The log file is your post-match witness"

At competition, when something goes wrong in a match, you have ten minutes between matches to diagnose it. Teams without logs are guessing. Teams with WPILOG files and AdvantageScope open the log, scrub to the moment of failure, and see exactly what every sensor and motor was doing at that instant. Motor stator current spiked? The intake jammed. Gyro drift during the turn? That's why the auto missed. State machine reads "EJECTING" when it should be "HOLDING"? There's the logic bug. Logs turn a mystery into a five-minute fix.

🔌 System Check — Logging Setup Verification

Before any competition practice:

  • Add DataLogManager.start() and DriverStation.startDataLog(DataLogManager.getLog()) to robotInit(). Deploy, enable for 30 seconds, disable. SSH into the roboRIO (ssh lvuser@roborio-XXXX-frc.local) and confirm a .wpilog file appeared in /home/lvuser/logs/.
  • Download the file and open it in AdvantageScope. Verify your SmartDashboard keys appear as log channels. If they don't, the log wasn't started before the first NetworkTables publish.
  • The roboRIO has limited flash storage (~512 MB). WPILib automatically deletes old log files when space runs low. If you need to keep a specific match log, download it immediately — don't assume it will still be there after five more matches.

Knowledge Check

1. Your robot deploys successfully but immediately shows ERROR in the Driver Station console after enabling. The first line of the stack trace you can see from your code is at frc.robot.subsystems.DriveSubsystem.<init>(DriveSubsystem.java:23). What does this tell you?

  • A An exception occurred on line 23 of a WPILib internal class.
  • B An exception occurred in the constructor of DriveSubsystem, on line 23. The <init> method name means "constructor." Something on line 23 — likely a hardware object being used before it's initialized — threw the exception.
  • C The error occurred in Robot.java line 23, inside robotInit().
  • D This is a WPILib deployment error, not a code error.

2. You want to leave a permanent sensor-health check in the code that notifies the pit crew if an encoder's value is outside the expected startup range. Which logging method should you use?

  • A System.out.println() — prints to the DS console and is easy to add.
  • B DriverStation.reportWarning() — creates a permanent amber WARNING entry that's easy to filter in the DS Messages tab and distinguishes this non-fatal condition from debug output.
  • C DriverStation.reportError() — marks it as high priority so the pit crew notices it immediately.
  • D SmartDashboard.putString() — displays the message on the dashboard for the drive team.

3. In a match, the robot's autonomous routine fails. You download the WPILOG and open it in AdvantageScope. The /Drive/EncoderDistance channel shows the encoder went from 0 to 72 inches correctly. The /Intake/HasPiece channel shows false the entire time. The /Auto/ActiveCommand shows the sequence stuck on "IntakeCommand" for 10 seconds. What most likely caused the autonomous failure?

  • A The drive command failed to reach its distance target.
  • B The beam break sensor never fired (HasPiece was always false), so IntakeCommand's isFinished() never returned true. The sequence stalled waiting for a game piece that never arrived — likely due to a missed game piece or a disconnected sensor.
  • C The WPILOG was corrupted — reliable data would show HasPiece change to true.
  • D The auto routine finished successfully but the drive team misidentified the failure.
💪 Practice Prompt

Instrument Your Robot for Competition Logging

  1. Add DataLogManager.start() and DriverStation.startDataLog() to Robot.java robotInit(). Deploy, run for 30 seconds, and confirm a WPILOG file is written. Open it in AdvantageScope — identify at least three logged channels from your SmartDashboard output.
  2. Add DoubleLogEntry and BooleanLogEntry fields to your IntakeSubsystem. Log motor speed and hasGamePiece() in periodic(). Verify they appear in AdvantageScope with correct values across a simulated intake cycle.
  3. Add a DriverStation.reportWarning() in your subsystem constructor that fires if an expected sensor read returns an out-of-range value at startup (e.g., encoder > 100 at init). Deliberately cause the condition and confirm the yellow WARNING appears in the DS Messages tab.
  4. Stretch goal: Add SmartDashboard.putData("Active Commands", CommandScheduler.getInstance()) in robotInit(). This logs the active command list. In AdvantageScope, find the /SmartDashboard/Active Commands channel and replay an auto run. Confirm you can see each phase of the routine by name in the timeline. This is the single most powerful tool for autonomous debugging.