Arcade drive

Arcade drive is a method of controlling the motors of a tank drive drivetrain using two axes of a controller, where one of the axes controls the speed of the robot, and the other the steering of the robot.

Arcade Drive

Robot CAD model, Controller image source

Deriving the equations

The equations used in the implementation are derived using linear interpolation. This allows us to transition from one coordinate to the other in a linear fashion, which provides a pleasant driving experience.

I won’t show the derivation here, since it isn’t too exciting (if you’re interested, it can be found in this post on Chief Delphi), but rather an illustration to help you understand the derivation more intuitively.

Arcade Drive Illustration

What we want is to transform our \(x\) and \(y\) coordinates to the speeds of the motor. To do this, let’s focus on the values we would like to be getting in the 1st quadrant. The left rectangle in the illustration represents the joystick values (in the 1st quadrant) and right one the speeds of the left and right motor (in the 1st quadrant). I would suggest you see the visualization at the end of the article, it demonstrates this nicely.

The speeds of the left motor \(l\) are \(1\) in all of the corners (besides the origin). Using \(x, y\), we can achieve the same values by saying that \(l\) is the bigger of the two… \(l = \text{max}(x, y)\).

As for the right motor \(r\), As the \(x\) and \(y\) change their values, \(r\) goes from \(1\) (top left) to \(-1\) (bottom right). We can model the same values using difference… \(r = y - x\).

A similar observation can be made about the other quadrants. This is mostly to show that you can think about the derivations more intuitively (since this particular one it isn’t too complicated).

Implementation

def arcade_drive(rotate, drive, left_motor, right_motor):
    """Drives the robot using arcade drive."""
    # variables to determine the quadrants
    maximum = max(abs(drive), abs(rotate))
    total, difference = drive + rotate, drive - rotate

    # set speed according to the quadrant that the values are in
    if drive >= 0:
        if rotate >= 0:  # I quadrant
            left_motor(maximum)
            right_motor(difference)
        else:            # II quadrant
            left_motor(total)
            right_motor(maximum)
    else:
        if rotate >= 0:  # IV quadrant
            left_motor(total)
            right_motor(-maximum)
        else:            # III quadrant
            left_motor(-maximum)
            right_motor(difference)

Examples

The following example demonstrates, how to make the robot drive using arcade drive controlled by a joystick.

# initialize objects that control robot components
left_motor = Motor(1)
right_motor = Motor(2)
joystick = Joystick()

# repeatedly set motors to the values of the axes
while True:
    # get axis values
    x = joystick.get_y1()
    y = joystick.get_y2()

    # drive the robot using adcade drive
    arcade_drive(x, y, left_motor, right_motor)

Visualization

Here is an interactive visualization of the sorts of values our function sets the motors to for different values of \(x\) and \(y\):

Closing remarks

If you are interested in reading more about this topic, I would suggest looking at this thread on Chief Delphi, where I learned most of the information about the theory behind arcade drive.