Telemetry and Debugging
Telemetry
In FTC, there are many situations in which you need to confirm the value of a variable, confirm the execution of a conditional branch, or simply inform the drive team about the state of the robot's program. The FTC control system has built-in support for telemetry, which effectively delivers any arbitrary message from the Robot Controller code to the Driver Station's screen. It is practically analogous to the print statement in a traditional computer program.
The OpMode
class contains a public field named telemetry
, which is where all telemetry actions are performed. Feel free to refer to the JavaDoc documentation for the Telemetry
interface for more details.
{% embed url="https://first-tech-challenge.github.io/SkyStone/doc/javadoc/org/firstinspires/ftc/robotcore/external/Telemetry.html" %} Official JavaDocs for Telemetry {% endembed %}
Telemetry works slightly differently compared to straightforward print statements. In telemetry, we build the driver station display line-by-line and then perform a bulk transmission to the Driver Station for this display to be shown. This mechanism takes into account the limited communication bandwidth between the Driver Station and the Robot Controller; to minimize disruption to the control system's other duties, there is a minimum time interval of 250 milliseconds between each bulk transmission of telemetry data. This is why the telemetry data shown on the Driver Station screen does not update very quickly. This mechanism will also affect how we write code for telemetry.
Writing Simple Data
In its simplest form, composing telemetry messages involves adding lines to the display by making calls to Telemetry.addData
and then sending the display to the Driver Station by calling Telemetry.update
. The following demonstrates this technique using some autonomous code from Relic Recovery by 5273.
// Adds telemetry of the drive motors
telemetry.addData("motorFL Pos", LPos);
telemetry.addData("motorFR Pos", RPos);
// Updates the telemetry
telemetry.update();
If LPos
and RPos
are both zero, executing this will cause the Driver Station to display the following information:
motorFL Pos : 0
motorFR Pos : 0
By default, calling telemetry.update()
will automatically clear the currently added data after it has been sent. Therefore, if you call telemetry.update()
twice in a row, the Driver Station will probably not show any data. You can override this behavior by using Telemetry.setAutoClear
.
Moreover, whereas calling telemetry.update()
is necessary in a LinearOpMode, it is not necessary in an iterative OpMode. telemetry.update()
is automatically called after each iteration of the loop()
method.
If you would like to send formatted data using the String.format
technique, addData
can optionally accept more arguments and pass them to String.format
with the second argument being the format string. For instance, if x
is equal to 3.141, calling telemetry.addData("Info", "Value of x is %.2f", x)
would result in "Info : Value of x is 3.14" on the Driver Station screen.
Simply using addData
in this manner is sufficient for most situations, but there are other options that may be more suitable for certain use cases.
Multiple Items per Line
If you would like multiple items to be shown in one line on the Driver Station, you can use the technique demonstrated below:
telemetry.addLine()
.addData("count", currentCount)
.addData("elapsedTime", "%.3f", seconds);
telemetry.addLine()
.addData("voltage", "%.1f", getCurrentVoltage())
.addData("orientation", "%s", getOrientation());
telemetry.update();
Managing Existing Items
The Telemetry.addData
method returns an object of the type Telemetry.Item
, which represents a single item on the Driver Station display. If you store the return value of addData
somewhere, you can reuse it later to make edits to the data, add more items to the display, or remove it from the display using the Telemetry.removeItem
function.
Logging
The Telemetry.log()
method returns an instance of Telemetry.Log
, an interface that supports message-based logging. Log messages are displayed under all other types of data on the Driver Station.
Debugging
Sometimes the Robot Controller app crashes without any useful information shown on the screen. Sometimes your code behaves erratically, and you would like to confirm a theory of a possible error using the value of a variable. In both situations, the most effective way to troubleshoot is to debug the program's execution. Since the Robot Controller app is debuggable, you can use the Debug button (pictured below) during upload to tell Android Studio to attach its debugger to the app.
The debugger in Android Studio supports the following features:
- View system logs with Logcat
- View the cause and the stack trace of a fatal exception
- Step through code, set breakpoints, and view the values of variables
- Evaluate code expressions at runtime
For a more comprehensive reference, visit Android's debugging documentation and IntelliJ IDEA's debugging documentation. Remember that Android Studio is based on IntelliJ IDEA.
Check your Understanding
- Why do we use telemetry?
- When do you need to add telemetry.update()?
- What are the functionalities of the Android Studio debugger?