The following is a quick overview that should help you use the Linear OpMode to program your FTC robot. We assume you’re using Android Studio to write and build your programs. Want to contribute information related to another method, or make a correction? Let us know.
This guide uses the DcMotor class as an illustrative example. A full list of classes can be found in the FTC App SDK javadocs. Since the Linear OpMode operates sequentially, it is a good option for those with prior programming experience. It has three main parts: initialization, the main code, and termination.
Variable Declaration
It is important to tell the program what variables will be used. It’s a good idea to declare them at the beginning of the class, as this allows them to be used in all of the methods we write. As a general rule, variables should only remain ‘alive’ so long as they are needed. In programming, we call this a variable’s scope.
1 2 3 4 5 6 7 |
public class YourClassName extends LinearOpMode { // Example: Declare a motor DcMotor arm_motor; //... } |
Note: In order to declare non-primitive types like DcMotor, we need to import them. This is done at the very top of the file after the package line:
1 2 3 4 |
package org.firstinspires.ftc.teamcode; // Example: Import the DcMotor class import com.qualcomm.robotcore.hardware.DcMotor; |
Initialization
The first step in creating a Linear OpMode is writing the initialization stage. This includes any code within the runOpMode() method and before the waitForStart() call. We use this section to declare any helper variables, map hardware to the variables we declared above, and perform any initial computations (like filling out a look-up table).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class YourClassName extends LinearOpMode { // ... @Override public void runOpMode() throws InterruptedException { // Declare any local / helper variables here // Our initialization code should go here // Example: Map the hardware to the arm_motor variable arm_motor = hardwareMap.dcMotor.get("arm"); // Wait for the game to start (driver presses PLAY) waitForStart(); // ... } } |
In this example, we’ve told our new Linear OpMode where to find the arm_motor variable. The string inside hardwareMap.dcMotor.get(...) will depend on what we labeled the motor in the robot controller’s configuration. Then we tell the program to wait for the driver to signal the start of the match.
Main Code
After the waitForStart() call comes the heart of the program: the place where we use sensors, set motors, and respond to stimuli. There are two main ways to structure this code, depending on what we want to accomplish: sequential instructions and while loops.
With sequential instructions, we give the robot a list of commands to run once. If the commands are completed prior to the end of the match, the robot will simply stop. This structure lends itself to autonomous programs, where we often have a list of tasks to accomplish in order. Here’s an example:
1 2 3 4 5 6 7 8 9 10 11 12 |
public void runOpMode() throws InterruptedException { // ... // Example: arm_motor.setPower(1.0); // Ask the program to wait for 2 seconds sleep(2000); // Stop movement after 2 seconds have passed arm_motor.setPower(0.0); } |
As we can see, this code follows from a list of instructions: give power, wait 2 seconds, stop power.
On the other hand, we can use while loops to run code many times in succession. This structure lends itself to situations in which we are reading from human input and sensors. For more complicated programs, we may want to start thinking about the program in terms of state machines (particularly for autonomous programs). Let’s see an example of looping to respond to human input:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public void runOpMode() throws InterruptedException { // ... while (opModeIsActive()) { // Example: double examplePower; // A local / helper variable // Sets the power of the arm motor to 1 // if the 'a' button is pressed on gamepad 1 // Otherwise, it sets the arm motor power to 0 if(gamepad1.a) examplePower = 1.0; else examplePower = 0.0; arm_motor.setPower(examplePower); // ... idle(); } } |
Note: Make sure to call idle() at the end of such a loop. This allows the program to perform other necessary tasks in between iterations of the loop.
Any code within the main while loop will run repeatedly until the driver presses ‘STOP’ on the driver station (which causes opModeIsActive() to return false).
Termination
The last part of a Linear OpMode is the termination phase. Any code we want to run at the end of your program should go here. Traditionally, this section is used to set each motor’s power to zero and servos to ending positions. The starting position for a servo is usually a good ending position.
1 2 3 4 5 6 |
//... // Example: Set the arm motor power to 0 (for safety) arm_motor.setPower(0.0); } |
Additionally, this would also be an ideal location for closing log files.
Conclusion
The following code is the full outline from above, using the loop structure. We’ve added a line immediately before the class declaration ( public class YourClassName...). This instructs the driver station to include our program in the list of available TeleOp programs. Replacing “TeleOp” with “Autonomous” will place it in the list of autonomous programs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package org.firstinspires.ftc.teamcode; // Import Statements @<span class="pl-smi">com.qualcomm.robotcore.eventloop.opmode.TeleOp(<span class="pl-c1">name</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">"Our Linear Code</span><span class="pl-pds">"</span></span>, <span class="pl-c1">group</span><span class="pl-k">=</span><span class="pl-s"><span class="pl-pds">"</span>Group Name<span class="pl-pds">"</span></span>)</span> public class YourClassName extends LinearOpMode { // Variable Declaration Code // Helper Function Code @Override public void runOpMode() throws InterruptedException { // Initialization Code while (opModeIsActive()) { // Main Loop Code idle(); } // Termination Code } } |