Tutorial 04: Drive a mecanum robot
You will build: a TeleOp that drives a mecanum robot, with slow mode, field-centric driving and reverse drive. The main track gives you all of this in one line: Drive.
You will learn: how to set up a mecanum drivetrain, check its motor directions, make the sticks feel good, add a slow mode, switch to field-centric driving, and drive “backwards”.
You need: a mecanum chassis with motors front_left, front_right, back_left,
back_right, and the hub’s IMU (imu). Tutorials 01-03. A block to lift the wheels off the ground.
Full program: Tut04MecanumDrive.java
Reference: drive.md, Signs and units
1. How mecanum wheels move
Section titled “1. How mecanum wheels move”Each mecanum wheel has rollers at 45 degrees. By spinning the four wheels in different
combinations, the robot can drive forward, sideways (“strafe”), turn, or all three at once.
The library does the math (in MecanumMixer). You only say what you want:
drive.drive(forward, strafeRight, turnClockwise); // each -1 to 12. Set up the drive
Section titled “2. Set up the drive”DriveConfig driveConfig = DriveConfig.mecanum();driveConfig.powerLimit = 0.6;MecanumDrive drive = new MecanumDrive(hardwareMap, driveConfig);DriveConfig holds the motor names, which motors are reversed, and the power limit. The
defaults (front_left … back_right, left side reversed) fit most goBILDA and REV chassis.
If your names differ, change them: driveConfig.frontLeft = "fl";.
powerLimit = 0.6 means no wheel ever gets more than 60%. Keep it low until everything works.
3. Check the motor directions FIRST
Section titled “3. Check the motor directions FIRST”If one motor is reversed wrongly, the robot spins or drifts in strange ways, and nothing else will make sense. Check before driving on the floor:
- Wheels off the ground (robot on a block).
- Run
MotorDirectionCheck(copy it like a tutorial program). Hold X, Y, A, B to spin one wheel each. - Every wheel must roll the way that would move the robot forward.
- Wrong one? Flip it in your config, e.g.
driveConfig.backRightReversed = true;.
4. The basic drive loop
Section titled “4. The basic drive loop”double forward = -gamepad1.left_stick_y;double strafe = gamepad1.left_stick_x;double turn = gamepad1.right_stick_x;drive.drive(forward, strafe, turn);Remember the minus on left_stick_y (the SDK says “up” is negative).
On the floor, check: stick up = forward, stick right = slides right, right stick right = turns clockwise. If it slides diagonally, two motor names are swapped between wheels.
5. Make the sticks feel good
Section titled “5. Make the sticks feel good”double forward = StickShaping.shape(-gamepad1.left_stick_y, 0.05, 2);double strafe = StickShaping.shape(gamepad1.left_stick_x, 0.05, 2);double turn = StickShaping.shape(gamepad1.right_stick_x, 0.05, 2);StickShaping.shape(value, deadband, exponent) changes the raw stick number before it goes to the motors:
- Deadband 0.05: sticks rarely rest at exactly 0. Without this, the robot creeps.
- Exponent 2: half stick gives a quarter of the power. Small moves become precise; a full push is still full power. Drivers usually love it. Try 1 (straight) and 3 (very soft) and pick.
6. Slow mode on a trigger
Section titled “6. Slow mode on a trigger”double speed = StickShaping.slowScale(gamepad1.left_trigger, 0.3);drive.drive(forward, strafe, turn, speed);Trigger let go = full speed. Pulled all the way = 30%. In between = in between. Great for lining up to score.
7. Field-centric driving
Section titled “7. Field-centric driving”With robot-centric driving (what we have so far), “stick up” means “where the robot faces”. When the robot faces the driver, everything feels backwards.
With field-centric driving, “stick up” always means “away from the driver”, whichever way the robot faces. It needs the IMU to know which way the robot faces. The IMU is a sensor inside the Control Hub that measures turning. The direction the robot faces is its heading, in degrees.
IMU imu = ImuSetup.get(hardwareMap, "imu", RevHubOrientationOnRobot.LogoFacingDirection.UP, RevHubOrientationOnRobot.UsbFacingDirection.FORWARD);...drive.driveFieldCentric(forward, strafe, turn, ImuSetup.headingDeg(imu), speed);The two directions must match how YOUR hub is mounted: which way the REV logo points and
which way the USB ports point. Wrong values = wrong heading = field-centric goes crazy.
Check: show ImuSetup.headingDeg(imu) on telemetry, turn the robot LEFT by hand: the number must go UP.
The heading is 0 where the robot pointed when the IMU started. Give the driver a button to say “forward is where the robot points now” (point it away from you first):
.bindPress(Pad.G1, Btn.BACK, imu::resetYaw)imu::resetYaw (two colons) is a short way to write the lambda () -> imu.resetYaw().
Yaw is the IMU’s word for heading.
The program toggles between the two styles with Y, with rumble confirmation (Tutorial 03).
8. Reverse drive
Section titled “8. Reverse drive”Sometimes the driver must look at the back of the robot (to load something). ReverseDrive
makes the back act as the front, for forward and strafe only:
ReverseDrive reverse = new ReverseDrive();.bindPress(Pad.G1, Btn.L_STICK_BTN, () -> confirm.play(reverse.toggle()))...drive.drive(reverse.apply(forward), reverse.apply(strafe), turn, speed);reverse.toggle() flips the mode and returns the new state, so confirm.play(...) buzzes twice
for ON and once for OFF. (Reverse only makes sense in robot-centric mode, so the program uses it there.)
9. Always stop in finally
Section titled “9. Always stop in finally”} finally { drive.stop();}Run it
Section titled “Run it”- Wheels off the ground: stick up, all wheels roll forward. Then on the floor, at 0.6 power.
- Forward, strafe, turn, and all three together all move as expected.
- Small stick moves are slow and smooth.
- Left trigger slows the robot down.
- Y (two buzzes): field-centric. Turn the robot 90 degrees and push stick up: it still goes away from you.
- BACK while facing away resets “forward”.
- Click the left stick (two buzzes): the back is now the front.
If something goes wrong
Section titled “If something goes wrong”| Problem | Fix |
|---|---|
| Spins when it should go straight | A motor direction is wrong. Section 3. |
| Slides diagonally when strafing | Two motor names are on the wrong wheels (e.g. front_left and back_left swapped). |
| Field-centric goes the wrong way, or circles | IMU directions do not match the hub, or “forward” was not reset while facing away. |
| Robot creeps with sticks let go | Raise the deadband to 0.08. |
| “MecanumDrive needs a MECANUM DriveConfig” | You used DriveConfig.tank(). Use DriveConfig.mecanum() or TankDrive. |
Try this
Section titled “Try this”- Change the exponent to 3 for turning only. Is aiming easier?
- Put field-centric ON by default.
- Make a “precision mode” toggle that sets a fixed
speed = 0.35, instead of the trigger. - Show which mode is active in big letters at the top of telemetry for the driver.
Tutorial 06: A fast, clear loop (or 05 if you also have a standard drivetrain)