DRAFT

PID Closed Loop Control for robotics

By Alex Brown 5/1/00

Introduction

PID (Proportional, Integral, Derivative) control laws will give you more control over your robot’s performance. While the most immediate robot applications would probably be for steering and speed control, the techniques can be applied to any kinds of motion.

There are two basic types of control we can use: dead reckoning, in which we estimate the commands necessary to achieve a goal ..such as applying 45% PWM to go forward at 6 inches per second and hope that the robot will travel at this speed; or we can monitor the results of the robot’s action and correct the commands to ensure that the goal is achieved. The more time the robot is correcting its performance rather than just charging ahead, the more accurate performance you’re going to get.

PID control systems provide continuous control. Hence, whenever we can operate under PID control, the performance will be much more reliable. The goal should be to operate under PID type control as much as possible and to save dead reckoning for only those times when there isn’t adequate sensor information available to do PID.

Control systems

There are two basic types of control systems. Open-loop control systems are those in which your controller tells your system to do something, but doesn’t use the result of that action to verify the results or modify the commands to see that the job is done properly. Closed-loop control continuously monitors the performance of your system and changes the commands as necessary to stay on track.

Open-loop control

Examples of open-loop control might be sending a PWM signal to your drive motor which you know will normally cause it to go forward at 6 inches per second, but not measuring the actual speed and therefore not knowing that the robot ran into a chair, or is climbing a slope, and isn’t really managing to go 6 inches per second. So you tell the robot to go forward for 10 seconds then turn right, expecting it to go 5 feet and enter a doorway. But it doesn’t make 5 feet and crashes into the wall. Or telling the robot to go straight forward for a distance by setting the steering position to center, and the robot slowly veers off to the side and crashes into the wall again.

The above block diagram shows the components of an open-loop control system. The “input reference” is the signal sent to the controller saying, perhaps, proceed forward at 6 inches per second. The “controller” block represents the calculations done to control some servo or motor or something on the robot. “Plant” is a control systems term that means everything that is affected by the controller. This may include a servo motor, the steering system of the robot, the motion of the robot in response to the steering and even the resulting position of the robot in its world. The “controlled variable” is whatever part of the plant your input reference is trying to control to. It can be the servo position, the steering angles or the position in the world. On a robot, the input reference, the controller function and parts of the plant may all be done by your microcontroller. From the earlier example, the input reference might be a command to go 6 inches/second, and the controlled variable can be the actual speed achieved which may, or may not be 6 inches/second.

Open-loop control is what dead reckoning is all about. Unfortunately, no matter how carefully we calibrate our motor and steering and other actuation devices of the robot such that the input reference should provide the desired result, there will always be errors which will cause the result to be different than what was planned. And since errors are usually cumulative over time, the longer you run in dead reckoning mode, the farther you’ll be from what you planned.

But, if open loop operations are short enough (and nothing keeps the robot from operating normally, like a chair), open loop control may provide adequate performance for many tasks.

Closed-loop control

Closed-loop control starts out like open-loop in that you send an input reference to the system, but then feedback is used to monitor the performance resulting from the command; and if the performance is different than desired, changes are made to the command to get back on track. This is done by comparing the input reference to the feedback signal and computing an error from the reference. The controller then has equations which adjust the commands to the plant to reduce the error.

Closed loop control is often approximated by doing long dead reckoning actions, then stopping and looking around, or finding a wall or corner in a known location, and using that reference to figure out how to get back on track. True closed loop control is continuously checking on performance (location, speed, whatever) so that the robot never gets significantly off track. For instance, to do wall following, the distance to the wall would be measured continuously and the steering adjusted continuously to maintain that distance. Or, in the speed control example above, if the reference speed is 6 inches per second, and the feedback signal indicates the robot is only moving at 5 ½ inches per second, the controller would see the error signal and increase the power to the motor.

To pick an example we can all identify with, steering a real car along a road is like a wall or line following exercise. You are fairly continuously changing the steering to keep the car centered in the lane. Imagine steering by aiming the car then closing your eyes and only opening them for a quick glimpse every 5 seconds or so to make a correction. It’s not only difficult, it’s scary. Because you’re afraid you might run into something during your dead reckoning phase. Same thing for a robot.

There are two aspects to this continuous control: one is the word continous, and the second is the equations to do the control. I’ll talk about continuous first.

“Continuous” really only exists in an analog world. Most of us are doing our robot control with digital computers, which can only calculate a command after some time period. But if you calculate the output often enough, it’s close enough to continuous to give the same effect.

For example, my current robot computes its steering commands 20 times a second. Effectively, it’s doing 1/20 of a second of dead reckoning followed by a control command update. Fortunately, it’s hard to get in much trouble dead reckoning for 1/20 of a second.

A sophisticated set of control equations will have many functions which are dependent on the rate at which they are calculated. For example: integrators, derivatives and filters are all time dependent. For this reason, it is necessary to have a software program (or at least part of the program) which executes at the desired repetition rate. This takes some type of a real-time operating system. This doesn’t have to be something you buy, or even something complicated. It can be done by polling (executing your software everytime a timer says the desired time has come), or by a real time interrupt which automatically runs your software when the time comes.

The interrupt is more flexible as you can have the software which is required to execute at a specific rate run when the interrupt occurs; and run other, non-time critical software in the background.

Polling software:

Start: Initialize anything that needs it

Set up timer to trip at desired rate.

Loop: Wait for timer to trip

(reset timer if necessary)

Do real time software tasks

Input sensors

Calculate commands

Output commands

Endloop

Interrupt driven software:

Start Initialize anything that needs it

Set up Interrupt to occur at desired rate.

Loop: Do background tasks, if any

Endloop

Interrupt: Do real time software tasks

Input sensors

Calculate commands

Output commands

Return

Either of the two schemes above will do the job. Effectively what you are doing is implementing a multi-tasking system. Each time the real time software is called, a small slice of many jobs may be performed. You may be controlling motor speed, controlling steering, controlling sonar and several other things, all at 20 times a second.

You will find that writing software where subroutines are entered repetitively to do a single job is a little different than usual. For example, when a job is first started, it may be necessary to initialize the equations. But, not to initialize them on subsequent entries. This may require other higher level software to set a flag indicating first pass (which the subroutine can reset after doing the intialization) or for the higher level software itself to do the intialization. I’ll try to put some examples in at the end to show how this can be done.

This sounds more complicated, and it is, but it’s worth it.

So, what about the equations?

PID equations come out a a branch of mathematics/engineering called “feedback and control theory”. The study of this is highly mathematical and gets really into differential equations, LaPlace transforms, Nyquist, Root-Locus and Bode analysis and other wonderful things. All this math is necessary to achieve optimal performance with good system stability.

However, I believe that for most simple systems (and most of our systems are simple), a good understanding of what the three equations (P, I and D) do will allow you to hack an adequate solution by trial and error.

PID stands for Proportional, Integral, and Derivitive. These are three basic calculations that can be used to control a system. You may find you can use just one, two or three to do a job.

Proportional control

The first and most basic part is the P, for proportional control. All this means is that if you have a reference you are trying to control to, you provide a control output proportional to the error from your reference.

(note: K is commonly used to represent such gain factors, and is usually given with a subscript indicating which gain is meant. E.g . Ksteering )

As a standard robot example (assuming a front wheel steering robot), if you are trying to follow a wall using a sensor that can measure the distance to the wall (e.g. sonar), you would turn your steering system to return you to the reference. If you are 2 inches to the right, you might turn your steering 4 degrees to the left. If 4 inches to the right, then turn the steering 8 degrees to the left. That is the proportional part.

A block diagram of this operation might look like:

The drawing indicates that the reference distance (the distance from the wall that you want the robot to stay at) is subtracted from the sonar distance. This gives you an error signal showing the distance from where you want to be in inches (or feet or whatever you want). The “O” where the two signals come together is called a summation point. The “+” indicates that the reference signal is added; and the “-“ means that the sonar sensor is subtracted to get the error signal. That is:

error = reference distance – sonar distance.

The steering gain block represents just a multiplier to get the desired amount of steering per inch of error. The whole thing can be written as:

Steering angle command = Ksteering * (reference distance – sonar distance)

So what this equation does is to steer the robot back toward the reference distance. Sounds like a good idea, but in reality, this isn’t enough. What will happen if we try to steer this way?

If the robot starts out dead center on the reference, it will continue to roll straight ahead. Very good, except in the real world, it won’t stay exactly on center. It will get off a bit to one side or the other. When it does it will turn back toward the reference; and will continue to keep turning until it gets back to the reference. And while the amount of steering gets smaller as it approaches the reference, it’s still turning in the same direction. So when it gets back to the reference, its now pointed in a direction to deviate onto the other side. As it goes out the other side, it will cause steering commands to turn back again, but it will just lead to the same problem of overshooting onto the original side.

If you make your gain fairly high, to get fast accurate performance, this simple proportional control law will probably be unstable causing the robot to go back and forth from side to side following a path similar to a sinusoid.

Now if you make your gains low enough, it may be that the robot will stay “close” to the reference. But in reality the robot will be continuously dithering back and forth from one side to the other. It may be a small acceptable amount of dither. The tradeoff would be that with low gains, your robot will probably be slow to return to the reference if errors occur, and may even go unstable with large deviations. (actually, as it was dithering back and forth, it never was really stable anyway.)

Later in this paper, there will be a computer simulation of a robot steering system where you can see this performance.