I'm the person who implemented the velocity PID controller in WPILib last summer. If I understand correctly, an integrator is necessary and sufficient to eliminate steady-state error in controlling a DC motor with a velocity PID controller in all cases. Here's some math:
I'll be using the model for a DC motor from
http://ctms.engin.umich.edu/CTMS/ind...stemModelin g, which has the following transfer function from voltage (V) to angular velocity (theta_dot):
P(s) = theta_dot(s)/V(s)=K/((Js+b)(Ls+R)+K^2)
First, we'll try controlling it with a P controller defined as:
C(s) = Kp
When these are in unity feedback, the transfer function from the input voltage to the error is:
E(s)/V(s) = 1/(1+C(s)P(s))
E(s) = 1/(1+C(s)P(s))*V(s)
= 1/(1+Kp*K/((Js+b)(Ls+R)+K^2))*V(s)
(See
http://ctms.engin.umich.edu/CTMS/Con...motorBlock.png for a diagram. I'm assuming that theta_dot_ref maps to the input voltage with a constant gain and that the measured signal is used as-is in the error calculation, so H(s) = 1).
In this case, we'll apply a step input, so V(s) = 1/s.
E(s) = 1/(1+Kp*K/((Js+b)(Ls+R)+K^2))*1/s
To find the steady-state value of a transfer function, we can apply the formula:
e_ss = lim_s->0 s*E(s)
e_ss = lim_s->0 s*1/(1+Kp*K/((Js+b)(Ls+R)+K^2))*1/s
= lim_s->0 1/(1+Kp*K/((Js+b)(Ls+R)+K^2))
= 1/(1+Kp*K/((0+b)(0+R)+K^2))
= 1/(1+Kp*K/(bR+K^2))
Notice that the steady-state error is non-zero. To fix this, an integrator must be included in the controller:
C(s) = Kp+Ki/s
Same steady-state calculations as before with the new controller:
E(s) = 1/(1+C(s)P(s))*V(s)
= 1/(1+(Kp+Ki/s)*K/((Js+b)(Ls+R)+K^2))*1/s
e_ss = lim_s->0 s(1/(1+(Kp+Ki/s)*K/((Js+b)(Ls+R)+K^2))*1/s)
= lim_s->0 1/(1+(Kp+Ki/s)*K/((Js+b)(Ls+R)+K^2))
multiplying by s/s:
= lim_s->0 s/(s+(Kp*s+Ki)*K/((Js+b)(Ls+R)+K^2))
= 0/(0+(0+Ki)*K/((0+b)(0+R)+K^2))
= 0/(Ki*K/(bR+K^2))
the denominator is non-zero, so e_ss = 0.
So mathematically speaking, an integrator is required to eliminate steady-state error in all cases for this model. If you don't want to use one, a feedforward can eliminate most if not all of the error if chosen carefully. Given that, there is always uncertainty, hence why feedback control exists.
Oblarg is correct that the behavior of the velocity PID tuning constants doesn't match the displacement PID. I tried to get something with close enough dynamics that teams could use a similar tuning procedure for both (except in the velocity case, there's no steady-state error so I made Ki not do anything).