Drivetrain Characterization
This section covers a control method known as characterization, as described in this paper and in WPIlib's documentation. In this section, we will develop the characterization formula for our drivetrain along with various tests to determine the constants needed to make the formula work.
Developing the Drivetrain Characterization Formula¶
Our previous method for driving the robot used the joystick values as a percentage of the maximum voltage we want to supply to the motors. But, let's say we wanted a more accurate control method  one based on math and physics. Drivetrain Characterization allows us to more accurately determine the voltage we should supply given a desired velocity and acceleration. This section will require an understanding of the concepts described in Part 1 and Part 2 of our basic electronic theory presentation.
Brushed DC motors work by running current through a coil of copper wires (known as the windings of the motor) as shown in the figure below. When current passes through these windings, a temporary magnetic field is created. Since there are permanent magnets in the motor, the armature (the part in the center connected to the coil of wires that is allowed to rotate) begins to accelerate towards the magnets. The north end of the armature is repelled by the north pole of the permanent magnet and the south end of the armature is repelled to the south end of the permanent magnet. As well, when the armature rotates so that the opposite poles are near each other, the yellow and blue wires are connected to the opposite ends of the coil. As a result, the flow of current reverses and the armature continues to rotates clockwise. This process repeats as long as there is voltage across the motor.
But what prevents the motor from accelerating indefinitely? Well, just as current running through the motor causes a torque that accelerates the armature, spinning the armature generates a voltage known as the counter electromotive force (or backEMF) because it opposes the voltage that was applied to the motor. Eventually, backEMF will cancel out the applied voltage. As a result, no current will flow through the windings and the rotational speed of the motor will reach a constant value.
Kirchhoff's voltage law states that the sum of the voltages in any closed loop in a circuit is zero. There are three voltages: a voltage we wish to apply , a voltage drop across the windings , and a voltage drop due to backEMF . If we apply Kirchhoff's voltage law, we get:
Which, by solving for , becomes:
Note
It is known that where is the current and is the resistance and where is the motor torque. Additionally where is the rotational speed of the motor. Since , we can create an equation for : where and are constants. For those who are inclined to do some calculus, you can find an equation relating rotational speed with time. The behavior of this function should match the behavior described earlier. The symbol means "proportional to". Everytime you see something like think of it as where is a proportionality constant.
The voltage due to backEMF varies directly with the speed of the wheels and therefore varies directly with the speed of the drivetrain, or . The voltage across the windings causes torque, which is proportional to the acceleration of the wheels and therefore the acceleration of the drivetrain, meaning . Finally, we need to account for any resistance we encounter in trying to move, such as friction. It so happens that this resistance is approximately constant no matter the desired velocity and acceleration. All that needs to be done is add a third constant  let's call it (other sources may call it ). Our new formula becomes:
Where is the sign function which returns 1 if , 1 if and 0 if . The reason we need the sign function is to make sure that always adds with the velocity term and never against it.
Note
The techniques described in this section can be used to determine formulas for controlling subsystems other than drivetrains, such as robot arms, elevators, or flywheel shooters. In these cases, determine the forces going against your system and include them in your equation. In most cases, the equation will take the form of some constant plus a velocity term and an acceleration term. However, some systems may need to add additional terms to counteract gravity, such as in elevator control
or arm control
.
This is the drivetrain characterization formula. In practice, however, we apply the drivetrain characterization formula to each side of the drivetrain and for each direction. That means we need equations for the left and right of the drivetrain and for each direction (wheels moving forward/backward).
where FL = left side moving forward, FR = right side moving forward, BL = left side moving backward, and BR = right side moving backward.
That's a lot of math!
Determining the Constants¶
To determine the drivetrain characterization constants , , and , we must isolate each dependent variable and gather data. We can then analyze the data using regression analysis (determining the bestfit line).
A situation in which velocity changes, but acceleration is constant, is one in which the applied voltage increases linearly; we call this behavior "quasistatic". The robot's acceleration is most pronounced when the voltage changes from a small value to a large value quickly; we call this behavior "dynamic".
For the tests, we record the voltage applied to each side of the drivetrain and measure the velocity and acceleration for each side. As well, we repeat each test twice: one for moving straight forwards and another for moving straight backward. Once we have collected the data, we can perform ordinary least squares regression to determine the constants.
This sounds like a lot of work to implement and, luckily enough, WPILib has a tool that greatly simplifies our work. You can check out instructions for using the tool here.
Using the Constants¶
You will need to initialize six objects: 1 SimpleMotorFeedforward
objects for each side and direction (4 total), and 1 PIDController
for each side. The constructor for each SimpleMotorFeedforward
will require the kS, kV, and kA we found in the previous section and each PIDController
will require the kP (and possibly kD) from the previous section.
Our characterized driving code will require two parameters: left and right, the desired speed of the wheels in m/s for the left and right sides. The code will then supply the motors with the correct voltage. Below are the instructions for creating our characterized driving code:

For the left and right sides, determine the desired acceleration of the robot by finding the change in velocity between our desired velocity and our current velocity and dividing by the change in time between the two measurements.

(Optional) Clip the acceleration at some maximum value. Note that the maximum acceleration the robot can achieve without the wheel slipping is where is the coefficient of static friction and is the gravitational acceleration.

Apply the drivetrain characterization formula for each side and direction using the
SimpleMotorFeedforward.calculate()
method. 
Determine the adjustment value for each side using the
PIDController.calculate()
method. 
If the robot is moving forward on the left side, the desired voltage is the sum of the left PID output and the forward left FF output; otherwise, the voltage is the sum of the left PID output and the backward left FF output. Repeat for the right side.

Divide by the maximum voltage and supply the final results to your drivetrain's
tankDrive()
method.
You should now have everything you need to implement your own code for a characterized drivetrain.