Skip to content
CrocoDocs
Starter GuideProgrammingEngineeringDesignPortfolio
Documentation

Introduction

IntroductionBIOBUZZ game overview

Getting started

Getting startedBlocksOnBot JavaAndroid StudioYour first OpModeJava basicsMotors and servosNonblocking codeDebugging robot code

Control systems

Control systemsJoystick mappingField-centric mecanum drivePID controlFeedforwardFlywheel velocity controlSystem identificationMotion profilingKalman filterLow-pass filter

Autonomous

AutonomousTimed and encoder movementOdometryLocalization troubleshootingMotion planningReliable autonomous sequencesPure PursuitSensor fusionAuto to TeleOp handoff

Season topics

Season topicsProjectile mathematicsTurret aimingShooting on the move

Code practices

Code practicesNaming conventionsCode organizationLoop timing and bulk readsFormattingComments and documentationTeam collaboration

Libraries

LibrariesNextFTCFTCLibSolversLibPedro PathingRoad RunnerFTC DashboardMercurial v2Mercurial v1PanelsSloth

Community software

Community softwareBlaze FTCOpenLoopHive Vision

Sensors and vision

Vision overviewVision basicsLimelight 3A
Starter Guide
Engineering
Design
Portfolio
Appearance

Joystick mapping

Turn gamepad input into simple, testable motor commands

Gamepad input

A gamepad stick gives a number between -1 and 1. Near the middle it is close to 0. On a typical gamepad, pushing the left stick up makes left_stick_y negative, so code often uses -gamepad1.left_stick_y to make forward positive.

A gamepad with its sticks, triggers, buttons, and directional pad identified.

The labels connected gamepads as gamepad1 and gamepad2. Check which driver holds each controller before assigning a .

InputKind of valueExample use
Stick axisAbout -1 to 1Drive forward, backward, or turn
Trigger0 to 1Gradually control an
Button or D-padtrue or falseOpen a claw or select a preset

Tank drive

Tank drive uses one stick for the left side and one for the right side. Configure the as left_drive and right_drive before running this example. Lift the drive wheels off the ground for the first test.

Tank drive: the left stick controls the left wheel and the right stick controls the right wheel.

package org.firstinspires.ftc.teamcode;

import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
import com.qualcomm.robotcore.hardware.DcMotor;

@TeleOp(name = "Tank Drive")
public class TankDrive extends LinearOpMode {
    @Override
    public void runOpMode() {
        DcMotor left = hardwareMap.get(DcMotor.class, "left_drive");
        DcMotor right = hardwareMap.get(DcMotor.class, "right_drive");

        waitForStart();
        while (opModeIsActive()) {
            double leftPower = -gamepad1.left_stick_y * 0.25;
            double rightPower = -gamepad1.right_stick_y * 0.25;
            left.setPower(leftPower);
            right.setPower(rightPower);
        }
        left.setPower(0);
        right.setPower(0);
    }
}
package org.firstinspires.ftc.teamcode

import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode
import com.qualcomm.robotcore.eventloop.opmode.TeleOp
import com.qualcomm.robotcore.hardware.DcMotor

@TeleOp(name = "Tank Drive")
class TankDrive : LinearOpMode() {
    override fun runOpMode() {
        val left = hardwareMap.get(DcMotor::class.java, "left_drive")
        val right = hardwareMap.get(DcMotor::class.java, "right_drive")

        waitForStart()
        while (opModeIsActive()) {
            val leftPower = -gamepad1.left_stick_y.toDouble() * 0.25
            val rightPower = -gamepad1.right_stick_y.toDouble() * 0.25
            left.power = leftPower
            right.power = rightPower
        }
        left.power = 0.0
        right.power = 0.0
    }
}

The 0.25 factor limits speed while you check motor direction. With both sticks forward, both wheels should move the forward. If one wheel turns backward, correct that motor's direction in hardware setup or code before raising the speed. Do not assume that the right motor must always be reversed; mounting varies.

Button input

A button is either pressed or not pressed. Inside the same loop, a simple claw action could look like this after you have mapped and checked a named claw:

if (gamepad1.a) {
    claw.setPosition(CLOSED_POSITION);
} else if (gamepad1.b) {
    claw.setPosition(OPEN_POSITION);
}

CLOSED_POSITION and OPEN_POSITION are values your team must measure for its own claw, between 0.0 and 1.0. This fragment illustrates the button logic; it is not a complete .

Control tuning

  • Dead zone: If a motor creeps while a stick is centered, treat a small input such as abs(value) < 0.05 as zero. Measure the drift on your gamepad before choosing the cutoff.
  • Speed limit: Keep the 0.25 multiplier for initial tests, then raise it gradually if the robot is controllable.
  • Telemetry: Show stick input and motor power during debugging so you can see whether a problem begins at the gamepad or motor.

Four-wheel and X-drive robots need a separate wheel-mixing calculation and careful checks of wheel order and direction. Once tank drive makes sense, check the geometry of your actual . Do not paste a wheel formula for a different layout into your robot.

For an X-roller mecanum drivetrain, continue with Field-centric mecanum drive. It starts with direction checks, then adds an heading so a stick direction stays aligned with the field as the robot turns.

Practice

Push only the left stick, then only the right stick. Predict which wheel will move before each test. When both sticks move together, explain why the robot goes forward or turns.

Sources

  • FTC's first gamepad-controlled motor example
  • GM0: Game Manual 0's drivetrain guide

Control systems

Learn how commands, sensors, and feedback affect robot motion

Field-centric mecanum drive

Rotate driver input into the robot frame and diagnose direction, heading, and drift problems

On this page

Gamepad inputTank driveButton inputControl tuningPracticeSources