Suppose you want to control a flywheel that will be used to shoot a ball towards a target. Suppose also that you need the ball to be going just the right speed so that it hits the target correctly. The simplest thing that you could do is to put a certain voltage on the motor so the flywheel so it is going just the right speed to work. This method is called "open-loop control" because you actually don’t know how fast the motor is spinning but you adjust the voltage so it "just works". The problem with this method is that if the motor heats up, or the battery voltage drops, or the temperature outside changes then the speed of the flywheel will change. Then you have to change the voltage that is sent to the motor to make it shoot correctly under the new conditions. It will always need to be tweaked to work because we don’t know what the angular velocity of the flywheel is when the ball is shot.
The basic idea of motion control is that you use a motor to move something and then use some kind of sensor to measure what the motor is doing. The sensor provides "feedback" about what the motor is actually doing. In the shooter example above we would have an encoder that would measure the RPMs of the flywheel. We would need to determine what RPM the shooter flywheel needs to spin to have the ball hit the target correctly. Then we need to "make sure" that the flywheel is going the correct RPM when we want to shoot the ball.
We can calculate the difference between the current flywheel RPMs and the target RPMs as the rpm error. PID control uses this calculation of error to adjust the motor voltage in order to "make sure" the flywheel spins the desired (target) RPM. The way we "make sure" that our flywheel is going the correct RPM is using a technique called PID control. PID stands for Position Integral and Derivative.
PID Control Overview
WPILib has a good discussion of PID Control in:
The videos below by FRC 0 to Autonomous are really good at describing PID and showing the PID loop calculations. The IZone parameter that they implement is not a very good solution and in general it is best if you can avoid integral control.
Feed Forward
We will continue with the flywheel shooter example from Motion Control. If you want your flywheel to achieve a certain RPM then you can use the fact that you know what the maximum RPM of the motor attached to the flywheel. Using this maximum RPM, you can make a good guess about what voltage will be required to get close to the target RPMs. For example if you are using a NEO Motor (see Table 1) then we know that it has a maximum speed of 5676 RPM when 12 volts is applied under no load. Lets assume that the motor has 1-to-1 gearing to the flywheel and our target RPM of the flywheel is 3000 RPM. We therefore want to spin the motor to (3000/5676) = 0.529 or 52.9% of its maximum speed. So we should be able to apply (0.529*12 volts) = 6.35 volts to the motor to get our desired 3000 RPM.
The idea of using the physics of the motor to estimate what the motor output should be is called "feed forward". Feed forward is used in addition of PID Control to achieve very good motor behavior. WPILib provides some classes to help do some of the feed forward calculations.
Smart Controller PID
WPILib provides classes to do PID calculations within the robot program however, smart controllers can perform PID calculations themselves. These "onboard" PID calculations are typically done at a much faster rate than is possible in the robot program (1ms vs 20ms). The faster PID calculations should provide better control of the motor.
PID Tuning
|
It is best if you can find PID values that do not use the Integral (kI) term. That is because including kI makes the PID controller have "memory" and can cause very unexpected behavior. Try to use only Kp, Kd and feed forward.
|
PID Units and Feed Forward Values
The WPILib frc2::PIDController
class can use any units the programmer decides to use since the measurement values are passed into the Calculate()
method which returns a percent output value from [-1,1]. Therefore the units of the PID constants will vary depending on the units used in the code. The feed forward classes in WPILib use the units library and are templated on whatever units are used to measure distance (either linear or angular).
Each software vendor uses different units for their PID Controllers. The table below summarizes the differences between the different vendor libraries.
Table 2. SparkMAX and Phoenix 6 TalonFX Onboard Controller Units
Control Type |
Controller Units |
Configurable |
Duty Cycle |
[-1,1] |
no |
Voltage |
[0,12] volts |
no |
Position |
rotations |
yes |
Velocity |
RPM |
yes |
Current |
Amps |
no |
The way the feed forward values are configured differs between the RevLib and Phoenix libraries. The RevLib Library (SparkMAX) only uses a single feed forward value (kFF
) which works the same as kV
in WPILib. There is also an Arbitrary feed forward value that can be used which can act like kS
in WPILib or can be customized (e.g. to vary with arm angle to compensate for varying gravity effect like kG
). The Phoenix 6 Library (TalonFX) uses kS
, kG
, kV
, and kA
for onboard control.
|
Links to the RevLib and CTRE Phoenix V6 APIs are in Resources.
|