Console Output Lesson

Console Output: Your First Debugging Tool

While the Driver Station logs provide a lot of information, one of the most powerful and easy-to-use tools for troubleshooting is simple console output using `System.out.println()`. It's an invaluable, real-time debugging tool that every programmer should master.

What is Console Output in FRC?

In Java, any time you use `System.out.println()`, that message isn't just printed in your IDE's console—it's also sent directly to the Driver Station logs as an `INFO` message. This allows you to use print statements to answer questions about your code's execution while the robot is running.

Using `System.out.println()` to Troubleshoot

By strategically placing print statements, you can follow the flow of your program and inspect the values of variables at different points in time.

1. Verifying Variable Values

One of the most common reasons for a bug is a variable not having the value you expect. Is a sensor returning a strange number? A simple print statement can answer this instantly.

// Inside a subsystem's periodic() method
@Override
public void periodic() {
    // This will continuously print the arm's angle to the Driver Station logs.
    System.out.println("Current Arm Angle: " + m_armEncoder.getDistance());
}
    

2. Confirming Code Flow

Sometimes, a bug is caused by a block of code not running at all. Print statements can act as "bread crumbs" to help you follow your program's path of execution.

// Inside a command's execute() method
public void execute() {
    System.out.println("Executing DriveDistanceCommand...");
    if (m_drivetrain.getDistance() >= 36.0) {
        System.out.println("Target distance reached!");
        // ...
    }
}
    

3. Tracking Command Lifecycles

It's very easy for a command to start and end before you expect it to. A common debugging technique is to add print statements in a command's lifecycle methods.

public class MyAutoCommand extends Command {
    @Override
    public void initialize() {
        System.out.println("MyAutoCommand: Initialized!");
    }

    @Override
    public boolean isFinished() {
        // Let's see why it might be ending early
        boolean isDone = m_sensor.isTripped();
        System.out.println("MyAutoCommand: isFinished() returning " + isDone);
        return isDone;
    }

    @Override
    public void end(boolean interrupted) {
        System.out.println("MyAutoCommand: Ended. Interrupted: " + interrupted);
    }
}
    

Best Practices

  • Be Specific: Instead of `println("value: " + x)`, use `println("Arm Motor Speed: " + x)`.
  • Remove When Done: Once you've fixed a bug, comment out or remove temporary print statements to keep the logs clean.
  • Use SmartDashboard for Permanent Values: If you need to monitor a value constantly (like a gyro angle), `SmartDashboard.putNumber()` is a cleaner solution.

Test Your Knowledge

Question: A command is ending much earlier than expected. To debug this, in which two command lifecycle methods would it be most helpful to place `System.out.println()` statements?