Skip to content
Week 4 · Lesson 4 55 min

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 LinearOpMode lifecycle from INIT to STOP.
  • Write a TeleOp OpMode using @TeleOp, waitForStart() and while (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.

InithardwareMap.get(...)waitForStart()Loopwhile (opModeIsActive())① read inputs② set outputs③ telemetryStop
INIT runs setup code, waitForStart() pauses, the loop runs while the OpMode is active, and STOP ends it.
  1. 1
    INIT pressed
    The SDK creates your OpMode and starts runOpMode(). Get hardware from hardwareMap and set directions here.
  2. 2
    Waiting
    waitForStart() pauses the program until the driver presses START (the play button).
  3. 3
    Running
    Your while (opModeIsActive()) loop reads the gamepad and sets motors and servos, over and over.
  4. 4
    STOP
    When STOP is pressed or the period ends, opModeIsActive() returns false, the loop ends, and the SDK stops the motors.
JAVA
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}
A complete two-motor tank drive TeleOp

Reading the gamepad

Left stick → Drive / strafeLeft trigger → IntakeD-pad → Lift presetsRight stick → TurnA / B → ClawRight trigger → Intake
Example mapping of gamepad sticks, triggers and buttons to robot actions.
InputJavaValues
Left stickgamepad1.left_stick_x, gamepad1.left_stick_y-1.0 to 1.0 (decimal number)
Right stickgamepad1.right_stick_x, gamepad1.right_stick_y-1.0 to 1.0
Triggersgamepad1.left_trigger, gamepad1.right_trigger0.0 (released) to 1.0 (fully pressed)
Buttonsgamepad1.a, b, x, y, left_bumper, right_bumpertrue while held, otherwise false
D-padgamepad1.dpad_up, dpad_down, dpad_left, dpad_righttrue while held
JAVA
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);
Arcade drive with powers clipped to the range -1 to 1

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.

JAVA
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}
A toggle that changes once per button press
  • Assign gamepads on the Driver Station: on Logitech-style controllers press Start + A for gamepad1 and Start + B for gamepad2; 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 gamepad1 and mechanisms to a second driver on gamepad2 when you are ready.
  • The cond ? a : b form picks a when cond is true and b otherwise; it is a short if/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

  1. 1Create the Tank Drive OpMode from this lesson, changing the motor names to match your configuration.
  2. 2Build it, select it on the Driver Station, and test with the wheels off the ground; fix motor directions if needed.
  3. 3Change it to arcade drive using Range.clip, then let each team member try both styles on the field tiles.
  4. 4Add a servo toggle on the A button using the previous-state pattern.
  5. 5Write a controls sheet listing every gamepad input your OpMode uses.
Deliverable: Your TeleOp source code with arcade drive and a servo toggle, and a one-page controls sheet with the team's preferred drive style.

Knowledge check

Answer every question, then check your answers.

  1. Q1A driver pushes the left stick fully forward. What value does gamepad1.left_stick_y give?
  2. Q2Where should you get motors from hardwareMap in a LinearOpMode?
  3. Q3Your new OpMode builds without errors but does not appear on the Driver Station. What is a likely cause?
  4. Q4Why does a toggle need the button's value from the previous loop?

Further resources

Mark lesson complete