The integral term
Removing the error that P leaves behind, and the windup that comes with it.
Do this lesson in the simulatorPrint it: worksheet (PDF) · answers (PDF) · as a web page
Guide: PID control explained
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")
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.
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.
Four defences, all standard, all one line:
- Clamp the integral to a sensible range, as above.
- Only integrate near the target, as the cell does. A long approach then adds nothing.
- 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.
- 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
- Set
Ki = 0and report the offset the robot settles at. - Remove the clamp and hold the robot back by hand for a few seconds. Describe the result.
- Plot the P term and the I term separately and watch which one is carrying the command at the end.