Driver Control
Turn gamepad input into predictable mecanum movement.
Turn gamepad input into predictable mecanum movement.
In this lesson, you will:
A driver should not need to understand your math during a match. Good TeleOp code makes common movement predictable and keeps surprises out of competition.
A mecanum roller meets the floor at roughly 45 degrees, so one powered wheel contributes both a forward-backward component and a sideways component. With the wheels mounted in the usual X pattern, some components reinforce one another while others cancel. The result depends on all four wheels, not on one wheel sliding the robot sideways by itself.
Forward contributes the same sign to all four wheels. Clockwise turn contributes positive on the left side and negative on the right. Right strafe contributes positive on the front-left and back-right diagonal and negative on the other diagonal. Adding those three contributions produces each wheel command.
For the front-left wheel, drive, strafe, and turn are all added. For the front-right wheel, strafe and turn are subtracted. The back wheels use the opposite strafe signs while keeping the same left-versus-right turn signs. Keeping the wheel order fixed makes the pattern much easier to audit.
When forward and strafe inputs have the same magnitude, two wheel commands reinforce and two cancel to zero. That is why the robot can move diagonally without a separate diagonal mode. Do not hardcode eight movement cases; continuously mix the joystick axes instead.
A joystick rarely rests at exactly zero. Treat small input values as zero before mixing the axes so the robot stays still when the driver releases the sticks.
Combined inputs can produce a command larger than 1.0. Dividing every wheel command by one shared denominator keeps every output inside the legal range while preserving the relationship between the wheels. Clipping only the oversized wheels changes that relationship and changes the requested direction.
For forward, strafe, and turn, predict the sign of all four wheel powers before the wheels move. Compare that prediction with telemetry one axis at a time. Then try one combined input and calculate the four raw and normalized values. Only connect those outputs to real motors after the math is internally consistent.
You already know how to read values from the controller. Let's use them to drive a mecanum robot. We have three things the driver can ask for: move forward or backward, move left or right, and turn. Our job is to combine those three inputs into one command for each wheel. For this lesson, positive y means forward, positive x means strafe right, and positive rx means turn clockwise. You will notice that y has a negative sign in the Java code. That is because pushing an FTC joystick forward normally gives us a negative Y value. We flip it once when we read the controller so that positive means forward everywhere else in our code. We are also going to keep the wheels in the same order for the entire video: front-left, front-right, back-left, and back-right. Keeping that order consistent makes the patterns much easier to see. Before we look at the code, it helps to see what the wheels are actually doing. A mecanum wheel has rollers mounted at about a 45-degree angle. Because of that angle, a spinning wheel pushes the robot both forward or backward and sideways at the same time. One wheel by itself would send the robot in a weird diagonal direction. With four wheels, we can make the parts we want add together while the other parts cancel out. On this goBILDA chart, the large arrow in the center shows which way the robot moves. The smaller arrows beside the wheels show how the wheels rotate. The green and blue arrows are used to distinguish the two wheel slants. They do not automatically mean positive or negative in our Java code. Look at the forward example first. All four wheels help push the robot forward, while their sideways pushes cancel each other out. For a right strafe, the forward and backward pushes cancel instead, leaving the sideways motion. For a turn, the wheels on the two sides work against each other and rotate the chassis. Now we can turn those movements into three simple sign patterns. Forward is the easiest one. All four wheels get the same positive command. For a right strafe, the signs alternate across the diagonals. Front-left and back-right are positive. Front-right and back-left are negative. For a clockwise turn, both wheels on the left are positive and both wheels on the right are negative. The final mixer is just those three patterns added together. Forward is added to every wheel. Strafe is added to one diagonal and subtracted from the other. Turn is added on the left and subtracted on the right. These signs describe the commands produced by our mixer. The motor direction settings on the real robot still depend on how the motors, gears, and wheels are installed. Now switch to Android Studio. This example does not control any motors yet. It only reads the controller, calculates the four wheel commands, and displays the results through telemetry. That lets us check the math by itself before connecting it to the robot. At the top of the loop, we read our three controls: forward, strafe, and turn. Forward has a negative sign because pushing an FTC joystick forward normally gives us a negative Y value. Next, the deadband treats any value very close to zero as zero. That keeps tiny joystick drift from becoming a movement command. Then we calculate a raw command for each wheel. Front-left adds forward, strafe, and turn. Front-right subtracts strafe and turn. Back-left subtracts strafe but adds turn. Back-right adds strafe and subtracts turn. Do not try to memorize four separate equations. Look for the pattern. Forward appears the same way in every equation. Strafe changes across the two diagonals. Turn changes between the left and right sides. These raw commands can sometimes be larger than one, so we calculate a denominator before using them. If the combined inputs are already within range, the denominator stays at one and nothing changes. If they are too large, we divide every wheel command by the same number. The important part is that all four commands are scaled together. That keeps the requested movement direction intact instead of changing only the wheels that went over the limit. Finally, telemetry shows the three inputs, the four raw commands, the denominator, and the four normalized commands. Move one joystick axis at a time and compare those numbers with the sign table before these outputs are ever connected to real motors. Here is one useful result of combining the inputs. Set forward and right strafe to 0.5, with no turn. Front-left and back-right become 1.0 because the two inputs add together. Front-right and back-left become zero because one input subtracts from the other. That gives us diagonal movement. We do not need a special diagonal mode or a separate if statement for every direction. The same mixer handles every angle of the joystick. Now let's look at a case that needs normalization. Forward is 0.8, right strafe is 0.6, and turn is zero. The raw wheel commands are 1.4, 0.2, 0.2, and 1.4. Motor power has to stay between negative one and positive one, so the two values at 1.4 are too large. If we clipped only those two values down to one, we would change the balance between the wheels. Instead, we divide all four values by 1.4. The final commands become 1.0, about 0.14, about 0.14, and 1.0. Now everything is in range, and we have kept the same relationship between the four wheels. You may see examples that multiply the strafe input by something like 1.1. That is a tuning choice used to compensate for imperfect sideways movement on a real drivetrain. Leave it out at first. Test the actual robot, and only add a correction if your results show that you need one. At this point, the math can look correct on the screen, but that does not prove the physical robot is set up correctly. When the team connects these outputs to the real motors, start with the controls released. All four commands should be zero. Then test forward, strafe, and turn one at a time at low power, with the robot safely supported and a mentor present. If the telemetry numbers are wrong, check the controller input or the mixer. If the telemetry is correct but the wrong wheel moves, check the hardware map, ports, and wiring. If the correct wheel moves in the wrong direction, check that motor's direction setting. Work through those layers in order. Find the first place where the result stops matching your prediction, fix that one problem, and test it again.
MecanumTeleOp.javaJava
double drive = -gamepad1.left_stick_y; double strafe = gamepad1.left_stick_x; double turn = gamepad1.right_stick_x; drive = Math.abs(drive) < 0.05 ? 0.0 : drive; strafe = Math.abs(strafe) < 0.05 ? 0.0 : strafe; turn = Math.abs(turn) < 0.05 ? 0.0 : turn; double fl = drive + strafe + turn; double fr = drive - strafe - turn; double bl = drive - strafe + turn; double br = drive + strafe - turn; double max = Math.max( Math.abs(drive) + Math.abs(strafe) + Math.abs(turn), 1.0 ); frontLeft.setPower(fl / max); frontRight.setPower(fr / max); backLeft.setPower(bl / max); backRight.setPower(br / max);
Use the goBILDA chart to record the expected physical wheel rotations for forward, right strafe, and clockwise turn. Separately, use this lesson's declared mixer convention to write the Java command signs in FL / FR / BL / BR order. Then calculate the raw and normalized commands for y = 0.8, x = 0.6, and rx = 0. With the robot safely supported and a mentor present, compare telemetry and wheel motion against each single-axis row before trying combined movement on the floor.
Check your understanding before moving on.
0 of 3 answered