Tank Drive

The tank-drivetrain is a system with 3 inputs and 2 outputs. These are:

  • Inputs
    • Z angle
    • Left-side distance
    • Right-side distance
  • Outputs
    • Left-side voltage
    • Right-side voltage

The primary problem with a tank-based system is the challenge of navigating from point A to B on the field. Much like a real-life tank, or even a car, tank-drive robots cannot strafe, which means navigation between two poses in space requires careful planning of a smooth arc through space.

Want to move 1 meter to the right? Much like parallel-parking a car, a tank-drive robot will need to determine the correct sequence of movements to get to that pose (generally an S curve in this situation).


When controlling a tank-drive robot, we never instruct the left and right tracks individually. Instead, we send the robot a movement vector, and rely on software to get to the new position as fast as possible. In order for this to work though, the robot must know where it is. This is done with out localization system.

By fusing the left and right distance measurements with the Z angle over time, we can perform dead reckoning to accurately estimate the robot's pose at any given point in time.

Implementing a Tank Drive DriveTrain

Lib5K provides a helper base class called DualPIDTankDriveTrain, which extends the base class for all drivetrains, AbstractDriveTrain. An example of implementing a drivetrain for autonomous movement can be found in this example.

The idea behind DualPIDTankDriveTrain is, Lib5K handles all the complex path planning code, and the user (you) is expected to implement function calls to the robot hardware. This lets us keep the same backend code, and switch out components like motor controllers and gyroscopes without needing to re-implement code.

When writing an AutonomousSequence, you can call one of the following methods on your drivetrain to get a pre-built path following, or on-the-spot turning command:

PathFollowerCommand createPathingCommand(Path path, double epsRadius);
TurnToCommand createTurnCommand(Rotation2d heading, Rotation2d epsilon, double maxSpeedPercent, boolean fieldRelative);

These methods are documented here and here.

You can also manually make the drivetrain drive to a pose, or face an angle using setGoalPose​ and setGoalHeading​.

For driver-operated control, see handleDriverInputs​ (example here).