TeleOp OpModes and Gamepad Controls
Build a complete TeleOp OpMode with `LinearOpMode`, understand its lifecycle from INIT to STOP, and map gamepad sticks and buttons to robot actions.
In this lesson you will
- Explain each stage of a
LinearOpModelifecycle from INIT to STOP. - Write a TeleOp OpMode using
@TeleOp,waitForStart()andwhile (opModeIsActive()). - Read gamepad sticks, triggers and buttons correctly, including the inverted Y axis.
- Program a button toggle that changes state only once per press.
Lesson
An OpMode is a program the drivers choose on the Driver Station. There are two kinds: Autonomous, which runs on its own, and Driver-Controlled (TeleOp), where drivers use gamepads. This week you write TeleOp. The easiest way is to extend LinearOpMode, which runs your runOpMode() method from top to bottom, like a story with a beginning, a middle loop and an end.
- 1INIT pressedThe SDK creates your OpMode and starts
runOpMode(). Get hardware fromhardwareMapand set directions here. - 2Waiting
waitForStart()pauses the program until the driver presses START (the play button). - 3RunningYour
while (opModeIsActive())loop reads the gamepad and sets motors and servos, over and over. - 4STOPWhen STOP is pressed or the period ends,
opModeIsActive()returns false, the loop ends, and the SDK stops the motors.
1package org.firstinspires.ftc.teamcode;
2
3import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
4import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
5import com.qualcomm.robotcore.hardware.DcMotor;
6
7@TeleOp(name = "Tank Drive", group = "Learning")
8public class TankDrive extends LinearOpMode {
9
10 @Override
11 public void runOpMode() {
12 // 1. INIT: get hardware and set it up
13 DcMotor left = hardwareMap.get(DcMotor.class, "left_drive");
14 DcMotor right = hardwareMap.get(DcMotor.class, "right_drive");
15 right.setDirection(DcMotor.Direction.REVERSE); // test which side on your robot
16
17 telemetry.addData("Status", "Initialized");
18 telemetry.update();
19
20 // 2. Wait for the driver to press START
21 waitForStart();
22
23 // 3. Repeat until STOP
24 while (opModeIsActive()) {
25 left.setPower(-gamepad1.left_stick_y);
26 right.setPower(-gamepad1.right_stick_y);
27 }
28 }
29}
Reading the gamepad
| Input | Java | Values |
|---|---|---|
| Left stick | gamepad1.left_stick_x, gamepad1.left_stick_y | -1.0 to 1.0 (decimal number) |
| Right stick | gamepad1.right_stick_x, gamepad1.right_stick_y | -1.0 to 1.0 |
| Triggers | gamepad1.left_trigger, gamepad1.right_trigger | 0.0 (released) to 1.0 (fully pressed) |
| Buttons | gamepad1.a, b, x, y, left_bumper, right_bumper | true while held, otherwise false |
| D-pad | gamepad1.dpad_up, dpad_down, dpad_left, dpad_right | true while held |
1// Arcade drive: one stick drives, the other turns
2// import com.qualcomm.robotcore.util.Range;
3double drive = -gamepad1.left_stick_y; // flip so forward is positive
4double turn = gamepad1.right_stick_x;
5
6double leftPower = Range.clip(drive + turn, -1.0, 1.0);
7double rightPower = Range.clip(drive - turn, -1.0, 1.0);
8
9left.setPower(leftPower);
10right.setPower(rightPower);
Buttons: held versus pressed once
The loop runs many times per second, so a button that is held for a quarter of a second is seen as true in many loops in a row. For actions like 'open while held' that is fine. For a toggle (press once to open, press again to close), you must react only on the loop where the button changes from not pressed to pressed. You do that by remembering the button's value from the previous loop.
1boolean clawOpen = false;
2boolean lastA = false;
3
4waitForStart();
5
6while (opModeIsActive()) {
7 boolean a = gamepad1.a;
8 if (a && !lastA) { // true only on the loop where A was just pressed
9 clawOpen = !clawOpen; // flip the state
10 }
11 lastA = a; // remember for the next loop
12
13 claw.setPosition(clawOpen ? CLAW_OPEN : CLAW_CLOSED);
14}
- Assign gamepads on the Driver Station: on Logitech-style controllers press Start + A for
gamepad1and Start + B forgamepad2; other controllers use the matching buttons. - Choose your OpMode from the TeleOp list, press INIT, wait for the status message, then press START.
- Give the main driver the drivetrain on
gamepad1and mechanisms to a second driver ongamepad2when you are ready. - The
cond ? a : bform picksawhencondis true andbotherwise; it is a shortif/else.
Key terms
- LinearOpMode
- An SDK base class whose
runOpMode()method runs from top to bottom, used for both TeleOp and Autonomous programs. - @TeleOp annotation
- A label above the class that makes the OpMode appear in the Driver Station's TeleOp list, with a name and optional group.
- waitForStart()
- A method that pauses the OpMode after INIT until the driver presses START.
- opModeIsActive()
- A method that returns true while the OpMode is running and false after STOP, used as the main loop condition.
- Toggle
- A control where each new button press switches between two states, detected by comparing the current and previous button values.
Practical exercise
Your first drivable TeleOp
- 1Create the Tank Drive OpMode from this lesson, changing the motor names to match your configuration.
- 2Build it, select it on the Driver Station, and test with the wheels off the ground; fix motor directions if needed.
- 3Change it to arcade drive using
Range.clip, then let each team member try both styles on the field tiles. - 4Add a servo toggle on the A button using the previous-state pattern.
- 5Write a controls sheet listing every gamepad input your OpMode uses.
Knowledge check
Answer every question, then check your answers.