Mecanum Tank drive

Our team has been trying to develop a program to allow us to drive our robot “Tank” style with two joysticks yet still have parallel control of the side-to-side movement of Macanum at the same time.
In a simpler way: With an Xbox controller, use the y-axis of each stick to control the forward-backward movement of each side, tank style, but still factoring in the value of side-to-side motion from the analog triggers.

We have tried to write many programs, and none of them have quite worked.
From scratch, simply writing something like this ends up only being able to control fwd/bkw or strafe, not both at the same time.

    public void SetRight(double RightY)
 {
        FrontRight.set(-RightY);
        RearRight.set(-RightY);
    }
    public void SetLeft(double LeftY) {
        FrontLeft.set(-LeftY);
        RearLeft.set(-LeftY);
    }
    public void Strafe(double RightX) {
        FrontLeft.set(RightX);
        RearLeft.set(-RightX);
        FrontRight.set(RightX);
        RearRight.set(-RightX);
}

So we tried to use the pre-existing function drive.mecanumDrive_Cartesian setup with the X value as simply the “x” trigger axis, and for the Y and Twist axis, averaging and getting the difference of the two sticks. (I can’t seem to upload the table that we made to prove it)

But even this algorithm does not seem to work. When we tested it, it seemed like the wheels were fighting themselves (something like if we told it to go sideways it would try to go both left and right at the same time)

Has anyone attempted anything like this? How should we proceed? Should we write a completely new function, or should we tinker with the pre-written ones?

First, it should be noted that a mecanum drive system won’t behave like a tank drive exactly. The behavior of mecanum wheels will prevent this; driving one side forward and the other forward with less power won’t cause tank-like movement. However, movement in this style is still possible.

To properly use a mecanum drive system, you need to express the heading as an angle and magnitude (in polar coordinates) as well as a rotational scalar. The first thing to do is to convert both of your Y-axes to a set of polar coordinates; the difference between the two should become the rotational scalar. Then, you factor the triggers into the rotational scalar.

Here’s what I’d try:

y_max=max(y1,y2)
y_min=min(y1,y2)
mag = S1*(y1+y2)/2
theta = arctan((y_max-y_min)/y_min)
rot = S2*(((y_max-y_min)/y_max)+S3*triggers)

Where y_max is the max of the two ys, y_min is the min, mag is the magnitude in polar coordinates, theta is the direction of movement, and rot is the rotational scalar for the robot. S1, S2, and S3 are constants. Using these values as well as a proper mix of sines and cosines, you can run a mecanum drive. Hopefully this should do what you’d like; conceptually it works in my mind, at least.

Hope it helps!

1 Like

I don’t know code what so ever, but I can tell you it is doable because some friends and I once had a VEX bot that ran Mecaunum tank and strafed sideways when you hit certain buttons on the controller. If you’re interested in the code I can try to get a teammate of mine to PM you.

Yes it will, for a properly set-up mecanum drive.

To properly use a mecanum drive system, you need to express the heading as an angle and magnitude (in polar coordinates) as well as a rotational scalar.

You don’t need to use polar coordinates. You can express the desired translational movement as X and Y components in a Cartesian coordinate system. In fact, those are the inputs expected by the mecanumDrive_Cartesian method in WPILib

Perhaps our team hasn’t been setting it up properly, then? I distinctly recall trying just that, and ending up with an arc depending on the degree to which it was powered. I’m not sure how one would explain this, though.

As for Cartesian vs. polar, most implementations of Cartesian processing I’ve seen simply convert to polar coordinates, then use sines and cosines. I guess it would be possible to do so otherwise, but it seems less simple and/or flexible, at least at first glance. That could definitely be wrong, though.

An arc is exactly what you would expect to get with a tank-drive User Interface when both joysticks are pushed forward, with one pushed further than the other.

If you are using Y[sub]L[/sub] and Y[sub]R[/sub] to control the left wheels and the right wheels, respectively, you will get essentially the same behavior from a mecanum drive as you would from a skid-steer vehicle.

As for Cartesian vs. polar, most implementations of Cartesian processing I’ve seen simply convert to polar coordinates, then use sines and cosines. I guess it would be possible to do so otherwise, but it seems less simple and/or flexible, at least at first glance. That could definitely be wrong, though.

The inverse kinematic calculations for mecanum are actually simpler with Cartesian inputs, and require no trigonometry. Polar inputs must be converted to Cartesian with trigonometry.

To get the full three degrees of freedom that a mecanum drivetrain supports, the user interface needs to generate three commands:

  • go forward/backward

  • strafe right/left

  • rotate clockwise/counterclockwise

Let’s call the above three commands FWD, STR, and RCW, respectively.

Then you provide those three commands to the mecanumDrive_Cartesian method method like so:

FWD goes to Y input

STR goes to X input

RCW goes to rotation input

So how do you generate FWD, STR, and RCW from 2 joysticks using only the Y axis of each joystick? You don’t. You need a third input. But if you want to drive the mecanum like a tank (ie, no strafing), you can do this:

FWD = (YL+YR)/2

RCW = (YL-YR)/2

STR = 0

A very awkward (for the driver) way to get all three degrees of freedom from a 2-joystick “tank drive” setup would be to use the X-axis of, say, the left joystick (XL) for strafe. Then you could do this:

FWD = (YL+YR)/2

RCW = (YL-YR)/2

STR = XL

Or you could use the right joystick for arcade drive, and use the X-axis of the left joystick to strafe:

FWD = YR

RCW = XR

STR = XL

Some teams have used a 3-axis joystick with a mecanum to get a Halo drive plus rotate:

FWD = Y

RCW = Twist

STR = X

Another option is to use modes with a single 2-axis joystick:

Arcade mode with button one pressed:

[INDENT]FWD = Y

RCW = X

STR = 0

Halo mode with button one not pressed:

FWD = Y

RCW = 0

STR = X[/INDENT]