Skip to content

A Systematic Debugging Workflow for FRC

learnfrc.com
learnfrc.comAuthor
Veer Bajaj
Veer BajajMaintainer

When the robot does something wrong, resist the urge to start changing code. Bugs are won by observing , not guessing. Use this triage order every time.

The DS is your ground truth. Check, in order: is the robot Communications light green (RIO reachable)? Is Robot Code green (your program is actually running)? Are there red text errors in the message box? A common panic – “my code does nothing” – is just code that crashed on boot; the DS message log shows the stack trace.

This tab shows CAN Bus Utilization and the 12V fault counter. High CAN utilization (>90%) causes dropped frames and laggy control. A 12V fault increment means a brown-out happened – more on that in its own lesson.

3. Replay the match with the DS Log Viewer

Section titled “3. Replay the match with the DS Log Viewer”

After a match, the Driver Station Log File Viewer plots voltage, trip time, roboRIO CPU%, lost packets, and robot mode over time, with event dots overlaid. Brown-outs show as a bright orange line. This is how you answer “why did the robot die for two seconds in the middle of teleop” without being there – the log already recorded it.

4. Inspect live data with AdvantageScope or Glass

Section titled “4. Inspect live data with AdvantageScope or Glass”

AdvantageScope visualizes NetworkTables, WPILib data logs, and DS logs – live or from a file. Its purpose-built tabs (Line Graph, Swerve, Odometry, 3D Field) turn raw numbers into pictures: plot a setpoint against its measured value to see a tuning problem instantly. Glass is the lighter live dashboard for plotting NetworkTables values and viewing field pose in real time.

5. Log structured data, not print statements

Section titled “5. Log structured data, not print statements”

WPILib’s Epilogue (new for 2025, Java-only) auto-generates logging from a @Logged annotation. Annotate your robot and subsystem classes and call Epilogue.bind(this) in the constructor; optionally DataLogManager.start() to mirror to disk:

@Logged
public class Robot extends TimedRobot {
private final Arm arm = new Arm();
public Robot() {
DataLogManager.start(); // also persist to a .wpilog file
Epilogue.bind(this);
}
}

Logged fields appear under structured NetworkTables paths derived from your class and field names, ready to plot. This is vastly better than System.out.println -- which, as the next lesson explains, can actually cause loop overruns.

Form a hypothesis (‘the elevator overshoots because kD is zero’), find the one piece of data that confirms or kills it (the position-vs-setpoint plot), and only then change code. One change at a time, re-test, keep notes. Reproduce the bug reliably before you believe any fix.

  • Triage in order: DS status lights -> message log -> CAN/Power tab -> DS log viewer -> AdvantageScope/Glass.
  • The Driver Station Log Viewer replays past matches with voltage, CPU, packet loss, and brown-out markers.
  • AdvantageScope and Glass turn NetworkTables/log data into plots and field views for live or post-match analysis.
  • Prefer structured Epilogue (@Logged, new for 2025) telemetry over print statements; observe before you change code.

This lesson was adapted from learnfrc.com.