The integral term

Removing the error that P leaves behind, and the windup that comes with it.

U5.4Feedback controlUniversity30 min

Do this lesson in the simulator

P responds to the error now. D responds to how it is changing. Neither has any memory, so neither can do anything about an error that is small, constant, and stubborn.

command = Kp * error + Ki * integral(error dt) + Kd * d(error)/dt

The integral adds up the error over time. A small error that refuses to go away accumulates, the I term grows, and eventually the command is large enough to move the robot. Then the error goes to zero, the integral stops growing, and it holds whatever value is needed to stay there.

That last sentence is the point: at steady state, the integral supplies the command and the proportional term supplies nothing. Which is what you want, because the proportional term can only supply something if the error is not zero.

In code

from bugbot import *
connect()

KP, KI = 1.6, 0.5
TARGET = 25.0
DT = 0.1
integral = 0.0

for tick in range(200):
    error = distance() - TARGET
    if abs(error) < 10:                           # only once it is close, see below
        integral += error * DT
    integral = max(-60, min(60, integral))        # clamped, see below
    plot("error", error)
    plot("i term", KI * integral)
    drive(max(-60, min(60, KP * error + KI * integral)), 0, 0)
    wait(DT)
stop()
print("ended", round(distance(), 1), "cm from the wall")

Run this in the simulator

On the chart, the error comes down to about 7 cm, which is where P alone would stop: at Kp = 1.6, 7 cm asks for 11 percent. Then, slowly, the last of it disappears as the I term climbs to about 13 percent, and by about 16 s the robot is on 25 cm. P gets you close; I finishes the job.

The error, and the P push and the I push, over twenty seconds of the PI controller051015200204060error, cmunder 9.4 cm, P asks for less than 15 %0510152001530time, secondspush asked for, %dead bandP + I(the same as P until 7 s)PI holds 14P about 0
Top: the error. Bottom: what each term asks for. Under 9.4 cm, P alone asks for less than 15 percent, which cannot move the robot. The integral starts once the error is under 10 cm and climbs until P + I is enough to move it again, and the last of the error goes. At the end P is about zero and the I term holds 14 percent on its own.

Windup

The integral is a memory, and memories can be wrong.

Suppose the robot is asked for 25 cm from the wall, and something is in the way at 40 cm. The error stays at 15, the integral grows, and grows, and grows. Ten seconds later the obstacle is removed. The integral now holds an enormous number, the command is pinned at full speed, and the robot charges past the target and keeps going until the integral has been unwound by an equally large error in the other direction.

That is integral windup, and it produces the worst overshoot you will ever see from a controller that is otherwise correct.

You do not need an obstacle to see it. Take the if out of the cell above and the integral starts adding up on the first tick, with the robot still 65 cm away. The I term reaches its clamp, 30 percent, within a second. The robot arrives with all of that still pushing, goes about 8 cm past the target, and sits there for about 7 s while the integral drains, before it creeps back.

The error and the I term with the integral near the target only, and with it adding up from the start05101520-200204060error, cmabout 8 cm past for 7 swith the ifwithoutthe if05101520-1501530time, secondsi term, %the clamp: 0.5 × 60 = 30
Green is the cell as it stands; red is the same cell without the if. Without it the I term hits its clamp of 30 percent after 0.9 s, while the robot is still far away. It arrives with all of that pushing, goes about 8 cm past, and sits there for about 7 s while the integral drains, before it creeps back.

Four defences, all standard, all one line:

  1. Clamp the integral to a sensible range, as above.
  2. Only integrate near the target, as the cell does. A long approach then adds nothing.
  3. Stop integrating while the output is saturated. If the actuator is already flat out, more integral cannot help, so do not accumulate it. This is called conditional integration.
  4. Back-calculate: subtract the amount by which the command was clipped, scaled, from the integral.

U5.6 is that problem on its own.

Choosing Ki

Ki has units of percent per centimetre per second. A useful way to think about it: Kp / Ki is roughly the time the integral takes to contribute as much as the proportional term. Make it comparable with the settling time you want, and start with an integral that acts slower than the P term, not faster. Too much Ki is its own kind of oscillation: slow, large, and with a characteristic look of the robot sailing past the target and turning round.

Task: no offset left

Settle exactly 25 cm from the wall, within 3 cm, from fourteen seconds onwards. Proportional control alone at a gentle gain will not do it: at Kp = 1.5 it stops about 8 cm short, because this drive does nothing below about 15 percent. Plot error and i term.

from bugbot import *
connect()

KP, KI = 1.5, 0.8
TARGET = 25.0
DT = 0.1
integral = 0.0

Challenges

  1. Set Ki = 0 and report the offset the robot settles at.
  2. Remove the clamp and hold the robot back by hand for a few seconds. Describe the result.
  3. Plot the P term and the I term separately and watch which one is carrying the command at the end.