Your First TeleOp from Scratch
Configure your drive motors on the Control Hub, then write, upload and run a Driver-Controlled OpMode that drives a mecanum robot with the gamepad sticks.
Our team is preparing this lesson. Written materials and practical exercises are available below.
In this lesson you will
- Create a robot configuration with clear, matching motor names
- Write a
LinearOpModewith@TeleOpthat loads four motors fromhardwareMap - Set motor directions so positive power always means forward
- Convert gamepad stick values into normalised mecanum wheel powers
- Upload, run and debug the OpMode using telemetry
Lesson
In this lesson you will build a complete Driver-Controlled (TeleOp) program step by step. By the end, one driver with one gamepad will be able to drive your robot forward, sideways and in turns. The code is written for a four-motor mecanum drivetrain, and a short tank drive alternative is included if your robot has normal wheels.
Step 1: Name your motors in the robot configuration
Your code never talks to a motor port directly. Instead, the Control Hub stores a robot configuration: a list that says which device is plugged into which port and what its name is. Your code asks for a device by that name. If the names do not match exactly, the program stops with an error, so set this up carefully first.
- 1Open the configuration screenPower on the robot and connect the Driver Station. Open the menu (three dots) and choose Configure Robot, then New (or Edit an existing configuration).
- 2Add the four drive motorsOpen the Control Hub, then Motors. For ports 0 to 3, pick the motor type that matches your hardware and type the names
front_left,front_right,back_leftandback_right. Names are exact:front_leftandFront_Leftare different, so use lowercase with underscores and write down which port each motor is plugged into. - 3Check the IMUOn a Control Hub the built-in IMU usually already appears on I2C bus 0 with the name
imu. Leave it there; you will use it in the next lesson. - 4Save and activatePress Done until you are asked to save, give the configuration a name such as
training_bot, and make sure it is the active configuration shown on the main screen.
Step 2: Understand the OpMode lifecycle
An OpMode is one program the drivers can pick on the Driver Station. A LinearOpMode runs from top to bottom: the code before waitForStart() runs when the driver presses INIT, the code after it runs when they press START, and a while (opModeIsActive()) loop keeps repeating until STOP is pressed or the match ends.
Step 3: Write the TeleOp
Create a new Java file called FirstTeleOp in the teamcode folder. In OnBot Java, connect your laptop to the Control Hub's Wi-Fi, open the OnBot Java page in a browser and add the file inside org.firstinspires.ftc.teamcode. In Android Studio, add it to the TeamCode module in the same package. Then type in this complete program.
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 = "First TeleOp", group = "Training")
8public class FirstTeleOp extends LinearOpMode {
9 @Override
10 public void runOpMode() {
11 // INIT: names must match the robot configuration exactly
12 DcMotor frontLeft = hardwareMap.get(DcMotor.class, "front_left");
13 DcMotor backLeft = hardwareMap.get(DcMotor.class, "back_left");
14 DcMotor frontRight = hardwareMap.get(DcMotor.class, "front_right");
15 DcMotor backRight = hardwareMap.get(DcMotor.class, "back_right");
16
17 // Motors on one side are mirrored, so reverse that side
18 frontLeft.setDirection(DcMotor.Direction.REVERSE);
19 backLeft.setDirection(DcMotor.Direction.REVERSE);
20
21 telemetry.addData("Status", "Ready - press START");
22 telemetry.update();
23 waitForStart();
24
25 while (opModeIsActive()) {
26 double y = -gamepad1.left_stick_y; // pushing forward gives a negative value
27 double x = gamepad1.left_stick_x; // strafe left/right
28 double rx = gamepad1.right_stick_x; // turn
29
30 // Keep every power between -1 and 1 without changing the ratios
31 double max = Math.max(Math.abs(y) + Math.abs(x) + Math.abs(rx), 1.0);
32 double fl = (y + x + rx) / max;
33 double bl = (y - x + rx) / max;
34 double fr = (y - x - rx) / max;
35 double br = (y + x - rx) / max;
36
37 frontLeft.setPower(fl);
38 backLeft.setPower(bl);
39 frontRight.setPower(fr);
40 backRight.setPower(br);
41
42 telemetry.addData("Sticks", "y %.2f x %.2f rx %.2f", y, x, rx);
43 telemetry.addData("Front L/R", "%.2f / %.2f", fl, fr);
44 telemetry.addData("Back L/R", "%.2f / %.2f", bl, br);
45 telemetry.update();
46 }
47 }
48}
- The
@TeleOp(name = ...)annotation puts the OpMode in the TeleOp list on the Driver Station. Without it, the OpMode never appears. - The call
hardwareMap.get(DcMotor.class, "front_left")looks up the motor by its configuration name. - Motor directions: motors on the left and right are mounted facing opposite ways, so the same power would spin them in opposite directions. Reversing one side means positive power drives every wheel forward. Which side to reverse depends on your motors and gearing, so you will test it.
- Forward is negative: on FTC gamepads, pushing a stick up gives a negative
left_stick_y. The minus sign in-gamepad1.left_stick_yturns forward into a positive number. - Normalisation: adding forward, strafe and turn can give values like 1.8, but
setPower()only accepts -1 to 1. Dividing all four by the largest possible sum keeps them in range and keeps the wheel speeds in the right proportion, so the robot still moves in the direction you asked. - Telemetry:
telemetry.addData()queues a line andtelemetry.update()sends it to the Driver Station screen. Use it to see what your code is thinking.
1// Each stick controls one side of the robot
2double left = -gamepad1.left_stick_y;
3double right = -gamepad1.right_stick_y;
4
5frontLeft.setPower(left);
6backLeft.setPower(left);
7frontRight.setPower(right);
8backRight.setPower(right);
9
10telemetry.addData("Left / Right", "%.2f / %.2f", left, right);
11telemetry.update();
Step 4: Upload, run and fix common errors
In OnBot Java, press Build Everything and wait for a successful build. In Android Studio, press Run with the Control Hub connected. On the Driver Station, assign the gamepad to user 1 by holding Start and pressing A. Choose First TeleOp from the TeleOp list, press INIT, then START. Test with the wheels off the ground first, then on the floor at low speed.
| Problem | Likely cause | Fix |
|---|---|---|
| Error: unable to find a hardware device named ... | Name in code and configuration differ, or the wrong configuration is active | Compare names letter by letter and activate the correct configuration |
| OpMode is not in the list | Missing @TeleOp, a @Disabled annotation, or the build failed | Add the annotation, remove @Disabled, rebuild and read the build errors |
| Robot drives backward or spins when you push forward | Wrong side reversed or one motor wired to the wrong port | Spin each wheel alone with telemetry and fix the directions or port names |
| Nothing moves but telemetry shows power | Gamepad not assigned, flat battery or loose motor cable | Press Start + A, charge the battery and check every connector |
| Strafing curves or drifts diagonally | Wheels mounted in the wrong pattern or uneven weight | Check wheel orientation against your kit instructions and Game Manual 0 |
Key terms
- Robot configuration
- A saved list on the Control Hub that gives each port's device a name your code can look up.
- hardwareMap
- The object your OpMode uses to get a motor, servo or sensor by its configuration name.
- LinearOpMode
- An OpMode that runs its code from top to bottom, pausing at
waitForStart()until the driver presses START. - Normalisation
- Scaling a set of motor powers so the largest is at most 1 while keeping their ratios the same.
- Telemetry
- Text your program sends to the Driver Station screen to show values while the robot runs.
Practical exercise
Build and tune your first TeleOp
- 1Create and activate a robot configuration with
front_left,front_right,back_leftandback_right. - 2Type in
FirstTeleOp, build it and run it with the wheels off the ground. - 3Push the left stick forward and check that all four wheels spin forward; fix motor directions if not.
- 4Put the robot on the floor and drive a square: forward, strafe right, backward, strafe left.
- 5Add a slow mode: when
gamepad1.left_bumperis held, multiply all four powers by 0.4.
Knowledge check
Answer every question, then check your answers.