Why does DifferentialDrive::ArcadeDrive do this?

The naiive implementation for an arcade drive looks something like this:

leftMotorOutput = xSpeed + zRotation;
rightMotorOutput = xSpeed - zRotation;

WPILib’s DifferentialDrive does a bit more. This is the code for the first quadrant, where speed and rotation are both positive, but you get the idea:

double maxInput = max(abs(speed), abs(rotation));
leftMotorOutput = maxInput;
rightMotorOutput = xSpeed - zRotation;

(See https://github.com/wpilibsuite/allwpilib/blob/master/wpilibc/src/main/native/cpp/drive/DifferentialDrive.cpp or https://github.com/wpilibsuite/allwpilib/blob/master/wpilibj/src/main/java/edu/wpi/first/wpilibj/drive/DifferentialDrive.java)

In effect, this slows down the motor on the outside of a turn, compared to the naiive implementation. This effect is most pronounced when the speed and rotation are equal: In both cases, one motor will be stationary, while the other wheel will be going twice as fast in the naiive implementation as in WPILib.

What is the reason they implemented it this way? How does it effect the ease of controlling the robot?

1 Like

If I’m reading your code right, the naive code will end up with a max over 1. The WPI code appears to be normalizing it so that the output in the fastest wheel doesn’t go above the maximum, but if you increase the turn rate it will decrease the other side instead.

3 Likes

Either way, the output will be capped at 1 by the motor controller’s code.

That is not necessarily true, and be careful assuming it is. A year or two ago we found that if you sent an out of range value the motor controllers would roll over. Always do you own error control and range checking.

In Addition, if you don’t normalize your turning ability will greatly decrease at high speed.

2 Likes