4 ms·
I find this really difficult to grok, not sure if it's the writing style or the incorrect formatting or if I just have a hard time understanding PID. Maybe a de
by robinduckett 9y ago
I find this really difficult to grok, not sure if it's the writing style or the incorrect formatting or if I just have a hard time understanding PID. Maybe a definition in line would be helpful, instead of a joke.
- Doxin 9y agoPID is a fairly simple concept. It's a way to control a process to reach a certain target value. So for example it might be used in an oven to drive the heating elements to keep a specific temperature. The way this works is by summing three different properties of error in varying quantities, where error is the difference between your actual value and the target value. So in the oven scenario the actual temperature might be 60c, with the target being 220c. Then the error is 220-60=160. The different properties are: - Proportional: This is simply the error multiplied by a preset constant. - Integral: This is all the previous errors summed together and multiplied by a preset constant. - Derivative: This is the speed of change in error multiplied by a preset constant. By tuning the P, I, and D constant you can change how your controller reacts to error. P simply tries to drive the system towards less error, more P equals a faster system, but might lead to overshooting the target and oscillating back and forth. I tries to correct for constant error. In the over example that might be heat leaking away. Too much I can lead to "windup": Any amount of error causing a long-lasting over-correction, causing overshoot again. D tries to dampen the system. Increasing it leads to a slower response and less oscillation. The way you generally tune these is by starting with all the constants set to 0. You then increase P until it starts oscillating. Then you increase D until it stops oscillating. For most systems leaving I set at 0 is good enough, but in case your system never reaches the target value you can start increasing it until it starts overshooting. Note that any amount of I will eventually force the system to the target value. It's only a question of how long it takes. I hope that helps.
- tzs 9y agoI've found the following a good way to visualize what a PID controller does, because it uses a situation that is easy to do a mental simulation of. Imagine you have a straight line painted on the ground in a large open area, and you are trying to program a self-driving car that moves at constant speed to follow the line. Your only input is how far to the side you are from the line. This is a signed number, with negative meaning you are to the left of the line and positive meaning you are to the right. Your only output is the angle to set the steering wheel to (in degrees). Positive angles turn to the right, negative to the left. The car starts out on the line and pointed in the right direction, with the steering wheel at 0. So how would you keep the car on the line? Some possible problems you have to deal with: the line might not be perfectly straight--it could wobble a little or occasionally slightly turn; there might be an occasional gust of wind the knocks you off course; the wheels may be slightly out of alignment so that the car pulls to one side, so setting the wheel to 0 doesn't necessarily mean you will go straight. The simplest thing that comes to mind is probably something like this, where "err" is how far off you are from the line, and "wheel" is the angle to set the wheel to: if err < 0: wheel = 15 elif err > 0: wheel = -15 else wheel = 0 As soon as that gets off the line for whatever reason, it ends up oscillating around the line in circular arcs that alternate direction. You can reduce the magnitude and frequency of oscillation by using a smaller steering angle, but then it takes you longer to get back to the line when you get off. We can address taking too long to get back to the line by replacing a constant steering angle with one that is small when we are close to the line and big when farther away. Let's make it proportional, so now our code is this: wheel = -err * Kp where Kp is a non-negative constant. In other words, we've made our steering proportional to the error. "Proportional" is the "P" in PID. Now when we get a big error, we respond big, so that does deal with the problem of taking a long time to correct a big error, but that introduces a couple new problems. First, when we reach the line we will be moving at a steep angle. We'll cross to the other side and rapidly accumulate error in the other direction. We'll strongly correct that, and so on, so we still have oscillation--and it is no longer shallow low frequency oscillation. It is now big and high frequency. Oops. Second, if we somehow get a big error, we could end up setting the steering angle high enough that we actually turn around enough to before reaching the line that we end up going the wrong way. Double oops! We can address this by taking into account how rapidly we are approaching the line. If we are approaching rapidly, we can back off on the wheel. We can do this by figuring out the rate of change of the error. In mathematical terms, we want the derivative of the error function. We can approximate that quite well by keeping track of past samples of the error. If we sample at times t1 and t2, and get e1 and e2, the derivative is approximately (e2-e1)/(t2-t1). So let's say we have the current derivative in variable D. Our code for updating the wheel after each sample is now: wheel = -err * Kp - D * Kd where Kd is a non-negative constant. "Derivative" is "D" in PID. Note that when we are to the right (positive error) and approaching the line, error is decreasing so D is negative, so the D term will be trying to lessen the correction from the P term. If we fiddle with Kp and Kd we hopefully can find some values so that as we get close to the line, the D term gets large enough to completely overcome the P term and more, so that instead of overshooting and oscillating we smoothly rejoin the line. If our steering is not aligned perfectly, so that wheel at 0 does not result in us going straight, the above PD controller does not end up following the line. The best you get is that it follows a straight line but displaced to the side from the real line. To fix that, we can keep track of the net error over time. In math terms, we want the integral of the error. This can be approximated by just keeping a running sum of all error samples (if we sample at a constant rate...if sampling at a variable rate you need to weigh them by the time since the prior sample). Let's say we have this available in a variable I. Incorporate this: wheel = -err * Kp - D * Kd - I * Ki where Ki is a non-negative constant. If our steering is biased to the right, that will tend to make I positive, so the I term will move the wheel to the left to counter the bias. "Integral" is the "I" in PID. So now we have a PID controller: while True: err = read_sensor() D = update_derivative(err) I = update_integral(err) set_wheel(-err * Kp - D * Kd - I * Ki) where update_derivative and update_integral are functions that take the current sample and based on it and past history estimate the current derivative and integral of the error function. If the sensor data becomes available at a fixed rate, and read_sensor() blocks until the next reading is available, then you can approximate the derivative simply by the difference between the current reading and the last reading, giving: last_err = 0 I = 0 while True: err = read_sensor() I += err D = err - last_err last_err = err set_wheel(-err * Kp - D * Kd - I * Ki) Normally you approximate a derivative by dividing the difference in readings by the time between the readings, but with the sensor being read at a fixed rate, the time difference is constant and so it can be rolled into Kd. Similar with Ki for the integral.