Skip to content

Drivetrain Java

En esta guía crearás un drivetrain mecanum (holonómico) usando Java y el SDK oficial de FTC, ya sea desde OnBot Java o Android Studio: el código es idéntico en ambos.

El objetivo es aprender:

  • Qué es un OpMode y cómo funciona LinearOpMode
  • Qué es un drivetrain mecanum y por qué es tan común en FTC
  • Cómo configurar motores con hardwareMap
  • Cómo leer el gamepad
  • Cómo combinar ejes de movimiento para mover el robot en cualquier dirección
  • Cómo compilar y correr el OpMode
  • Cómo probarlo desde Driver Station

Un OpMode es una clase que corre en el Control Hub y controla el robot durante un período: TeleOp (control manual) o Autonomous (rutina automática).

LinearOpMode es el tipo de OpMode más común para empezar: se ejecuta de forma lineal, de arriba hacia abajo, con un bucle principal controlado por opModeIsActive().


Un drivetrain mecanum usa 4 ruedas con rodillos montados en ángulo, formando una X vista desde arriba. Esto le permite al robot moverse en cualquier dirección (adelante, atrás, lateral) sin girar las ruedas ni cambiar su orientación.

Es uno de los drivetrains más usados en FTC, mucho más que en FRC.


Asegúrate de tener:

  • OnBot Java accesible o Android Studio con el proyecto FtcRobotController abierto
  • Driver Station instalada y conectada al Control Hub
  • Control Hub configurado
  • Gamepad conectado
  • 4 motores mecanum cableados y conectados al Control Hub o Expansion Hub

Crearemos un OpMode con:

  • 4 motores DcMotor
  • Lectura del gamepad 1
  • Cálculo de potencia por motor combinando 3 ejes de movimiento
  • Normalización de potencias
  • Control desde TeleOp
Motores
├── front_left_drive
├── back_left_drive
├── front_right_drive
└── back_right_drive

Nombrar los motores en la configuración del Robot Controller

Section titled “Nombrar los motores en la configuración del Robot Controller”

Antes de escribir código, los motores deben existir en el archivo de configuración del Robot Controller, con nombres exactos.

  1. Toca los tres puntos verticales en la esquina superior derecha de la app Driver Station para abrir el menú.
  2. Selecciona Configure Robot para abrir la pantalla Configuration.
  3. Toca la palabra Motors para abrir la pantalla Motor Configuration.
  4. Repite esto para los 4 motores: usa el selector desplegable de cada puerto para elegir el tipo de motor, y usa el teclado en pantalla para escribir su nombre — usaremos front_left_drive, back_left_drive, front_right_drive, back_right_drive.
  5. Presiona Done para completar la configuración de cada motor.

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

@TeleOp(name="Mecanum Drive", group="TeleOp")
public class MecanumDrive extends LinearOpMode {
private DcMotor frontLeftDrive = null;
private DcMotor backLeftDrive = null;
private DcMotor frontRightDrive = null;
private DcMotor backRightDrive = null;
@Override
public void runOpMode() {
}
}

name es el texto que verás en el dropdown de Driver Station. group te permite organizar varios OpModes relacionados.


Dentro de runOpMode():

frontLeftDrive = hardwareMap.get(DcMotor.class, "front_left_drive");
backLeftDrive = hardwareMap.get(DcMotor.class, "back_left_drive");
frontRightDrive = hardwareMap.get(DcMotor.class, "front_right_drive");
backRightDrive = hardwareMap.get(DcMotor.class, "back_right_drive");

frontLeftDrive.setDirection(DcMotor.Direction.REVERSE);
backLeftDrive.setDirection(DcMotor.Direction.REVERSE);
frontRightDrive.setDirection(DcMotor.Direction.FORWARD);
backRightDrive.setDirection(DcMotor.Direction.FORWARD);

telemetry.addData("Status", "Initialized");
telemetry.update();
waitForStart();

while (opModeIsActive()) {
}

Este bucle se repite continuamente mientras el OpMode está corriendo, hasta que el driver presiona STOP.


Dentro del bucle:

double axial = -gamepad1.left_stick_y;
double lateral = gamepad1.left_stick_x;
double yaw = gamepad1.right_stick_x;
  • axial: avance/retroceso. Se invierte porque el stick entrega valores negativos hacia arriba.
  • lateral: movimiento lateral (strafe), propio de un drivetrain mecanum.
  • yaw: rotación del robot.

double frontLeftPower = axial + lateral + yaw;
double frontRightPower = axial - lateral - yaw;
double backLeftPower = axial - lateral + yaw;
double backRightPower = axial + lateral - yaw;

double max = Math.max(Math.abs(frontLeftPower), Math.abs(frontRightPower));
max = Math.max(max, Math.abs(backLeftPower));
max = Math.max(max, Math.abs(backRightPower));
if (max > 1.0) {
frontLeftPower /= max;
frontRightPower /= max;
backLeftPower /= max;
backRightPower /= max;
}

frontLeftDrive.setPower(frontLeftPower);
frontRightDrive.setPower(frontRightPower);
backLeftDrive.setPower(backLeftPower);
backRightDrive.setPower(backRightPower);

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="Mecanum Drive", group="TeleOp")
public class MecanumDrive extends LinearOpMode {
private DcMotor frontLeftDrive = null;
private DcMotor backLeftDrive = null;
private DcMotor frontRightDrive = null;
private DcMotor backRightDrive = null;
@Override
public void runOpMode() {
// Get motors from hardware configuration
frontLeftDrive = hardwareMap.get(DcMotor.class, "front_left_drive");
backLeftDrive = hardwareMap.get(DcMotor.class, "back_left_drive");
frontRightDrive = hardwareMap.get(DcMotor.class, "front_right_drive");
backRightDrive = hardwareMap.get(DcMotor.class, "back_right_drive");
// Invert left side
frontLeftDrive.setDirection(DcMotor.Direction.REVERSE);
backLeftDrive.setDirection(DcMotor.Direction.REVERSE);
frontRightDrive.setDirection(DcMotor.Direction.FORWARD);
backRightDrive.setDirection(DcMotor.Direction.FORWARD);
telemetry.addData("Status", "Initialized");
telemetry.update();
waitForStart();
while (opModeIsActive()) {
double axial = -gamepad1.left_stick_y;
double lateral = gamepad1.left_stick_x;
double yaw = gamepad1.right_stick_x;
double frontLeftPower = axial + lateral + yaw;
double frontRightPower = axial - lateral - yaw;
double backLeftPower = axial - lateral + yaw;
double backRightPower = axial + lateral - yaw;
double max = Math.max(Math.abs(frontLeftPower), Math.abs(frontRightPower));
max = Math.max(max, Math.abs(backLeftPower));
max = Math.max(max, Math.abs(backRightPower));
if (max > 1.0) {
frontLeftPower /= max;
frontRightPower /= max;
backLeftPower /= max;
backRightPower /= max;
}
frontLeftDrive.setPower(frontLeftPower);
frontRightDrive.setPower(frontRightPower);
backLeftDrive.setPower(backLeftPower);
backRightDrive.setPower(backRightPower);
telemetry.addData("Front left/Right", "%4.2f, %4.2f", frontLeftPower, frontRightPower);
telemetry.addData("Back left/Right", "%4.2f, %4.2f", backLeftPower, backRightPower);
telemetry.update();
}
}
}

Método obligatorio de todo LinearOpMode. Contiene toda la lógica del OpMode: inicialización, espera de Start y el bucle principal. Se ejecuta una sola vez cuando el driver selecciona y corre el OpMode.


  1. Guarda el archivo.
  2. Si usas OnBot Java: presiona Build. Si usas Android Studio: presiona Run (▶).
  3. Abre Driver Station.
  4. Selecciona Mecanum Drive en el dropdown de TeleOp.
  5. Presiona INIT y luego START.

Abre Driver Station y verifica:

  • El Robot Controller aparece conectado
  • El OpMode Mecanum Drive aparece en el dropdown
  • No hay errores rojos al presionar INIT

  • Revisa errores de sintaxis señalados en rojo
  • Confirma que los nombres de los motores coincidan con Configure Robot
  • Reinicia OnBot Java o Android Studio

Ahora puedes continuar con:

  • Corriendo el programa
  • Drivetrain Blocks, si quieres comparar ambas rutas
  • Autónomo básico
  • Sensores (IMU, encoders)
  • Visión (AprilTags, TensorFlow)
FTC SDK