Note: Precomputing PID gains for a velocity shooter using pole/zero placement

I wanted to post some formula’s for deriving P and I gains for a velocity PID control loop such as a shooter used in the 2012 Rebound Rumble game.

a) motor L/R time constant is small relative to motor control frequencies.
b) The system ( motor , gearbox and wheel)  first order time constant tau_m is known.
c) The input speeds are normalized to the maximum motor speed, w_max. w_max = 12v/ke*60/2pi rpm which is approx w_free of the motor.
d) The desired motor response time constant, tau_d, is smaller than the motor tau_m by a factor of r.

Then the integral gain KI is given by

KI = 1/tau_d

and the proportional gain KP is given by

KP = r = tau_m/tau_d ;

If the integral computation used in the PID loop doesn’t contain a dt factor (i.e it is just an error accumulation) as is typical of the WPILIB PIDcontroller then the KI must be multiplied by the PID update period.

KI_WPILIB = T/tau_d where T is the PID period.

If you are feeding back RPM then the gains must be divided by  w_max.


The 599 shooter wheel has an open loop time constant tau_m = .68 sec

We want to have a tau_d  =  .33  sec which means the error should be around 5%  of the target by 1 second (three time constants).   During autonomous this would be the delay before we can shoot.

KI = 1/tau_d = 3.

KP = tau_m/tau_d = 3*.68 = 2.04 ;

For WPILIB  we want KI_WPILIB  = T*KI = .05*3 = .15   ;  KP remains the same.

The shooter has a w_max = 5614 rpm  so if the feedbacks are not normalized then KP and KI must be divided by w_max. or

KP = 2.04/5614 = 3.63 e-4 ;  KI_WPILIB = .15/5614 = 2.49e-5 ;

That’s it.   The main factor limiting the value of KP is the magnitude of the noise on the RPM feedback signal.   Typically after filtering this can get down to 1% of the RPM.  KP multiplies the noise so to keep the noise below 5% then the max KP would be 5.

theoretical derivation:

The transfer function G(s) of the motor is  1/(tau_m*s + 1).

The transfer function of the PID compensator  GC(s) is  (KP + KI/s) or KI*(KP/KI*s + 1)/s

The closed loop transfer function   =   GC(s)*G(s)/(1+GC(s)*G(s))

Lets look at the product  GC(s)*G(s) = (KI/s)*(KP/KI*s +1)*/(tau_m*s +1)

If we place the zero exactly at the motor pole then they will essentially cancel each other and we are left with GC(s)*G(s) = KI/s  and  now KP/KI = tau_m.

So the resulting closed loop transfer function is now   KI/s/(1 + KI/s)  = 1/(1/KI*s +1)  and since we defined 1/KI as tau_d we have a new closed loop response that looks like a more responsive motor with a transfer function of  1/(tau_d*s + 1).

See  this for additional discussion on obtaining tau_m and software implementation of PID loops.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: