Every application has some sort of entry point - a specific well known and consistent place where the very first line of code that will be run lives. For standard Java applications this is the public static void main(String[] args) method, which can be found inside a single class within your application.
For FIRST Tech Challenge, that main method is not something we need to worry about directly. It exists as part of the Robot Controller app, but it's already been provided as it also needs to initialize a lot of other stuff (like communications to the Driver Station, the Self Inspection, and the basic framework we'll be using to communicate to the robot hardware). The important part for FTC is the OpMode. There are two types of OpMode available, with the LinearOpMode being the easiest to use if you're just getting started.
You can find a sample Linear OpMode in the src/main/java/org/firstinspires/ftc/robotcontroller/external/samples folder of FIRST's Robot Controller source core repository on GitHub.
Here are the important parts of the Linear Opmode:
Package & Imports
The first line in a Java file contains the "package" in which the file lives. This also relates to the folder in which the file will be found. All team code should be in the teamcode folder.
package org.firstinspires.ftc.teamcode;
The Imports section contains various lines that look like this:
import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
import com.qualcomm.robotcore.eventloop.opmode.Disabled;
import com.qualcomm.robotcore.hardware.DcMotor;
import com.qualcomm.robotcore.util.ElapsedTime;
import com.qualcomm.robotcore.util.Range;
These lines tell the compiler that we want to use various objects that have already been defined elsewhere (like the abstract LinearOpMode itself).
The OpMode Class
After the Imports section, we define the class itself. The class definition consists of everything between the opening curly brace ({) after the expression extends LinearOpMode and continues through to the matching close curly brace (}).
@TeleOp(name="Basic: Linear OpMode", group="Linear Opmode")
@Disabled
public class BasicOpMode_Linear extends LinearOpMode {
/*
...
... Everything inside this set of braces is part of the class.
...
*/
}
The line @TeleOp(name="Basic: Linear OpMode", group="Linear Opmode") is a Java Annotation which is used to decorate the class with the information about how that class should be presented in the Driver Station user interface.
The next line (@Disabled) is another annotation. This one, which is present in all the sample OpModes, is used to hide the OpMode in the Driver Station. This can be especially useful for experimental OpModes that you might not want to use by accident during a competition.
Finally, we get to the class definition itself.
public means that the class will be visible to classes outside the package in which the class is defined (as long as that package has been imported by the class consuming it).
class means that what we are defining is a Java class (as opposed to an interface, enum(eration) or similar).
BasicOpMode_Linear is the name you are assigning to this specific thing being defined. Behind the scenes, the robot controller application will be creating a new instance of this class when you select it from the Driver Station's user interface.
extends is another Java keyword, and what it means is that you're going to take another existing class (in this case the LinearOpMode) and use that as a building block to which you'll be adding additional functionality.
Finally LinearOpMode is the thing we're extending. LinearOpMode is an abstract class. This means it's not fully complete. Specifically the LinearOpMode defines that there needs to be a runOpMode method (where the OpMode specific code will live), but does not provide an implementation. Any class that extends LinearOpMode needs to provide that method for itself.
The runOpMode Method
This method contains the code that will be triggered when the OpMode is selected. This method should consist of three portions:
-
Any initialization that is necessary, followed by a call to
waitForStart()or a loop for which the termination condition is thatisStarted()returnstrue. This initialization usually includes querying the HardwareMap for the sensors and actuators that the OpMode will be using. -
A loop (typically a
whileloop), including a termination clause that will be triggered whenisStopRequested()becomestrueoropModeIsActive()becomesfalse. -
Any "cleanup" code that should be run after the "Stop" button is pressed. This may include things like turning off any devices that need special handling, or resetting things to a known position. (For example, if there is a fragile component that is in a position where it could be damaged you might choose to move it or move a cover over it.)