PID Controller

From The UAV Guide Wiki
Jump to: navigation, search

Overview

The proportional-integral-derivative controller, or PID controller, is the most common type of controller used for UAV stabilization and autonomous control. It is a type of control loop feedback controller that attempts to drive some UAV flight parameter to a given desired value. This method can be applied to stabilize or control almost all aspects of an UAV's flight such as flight speed, altitude and orientation, and for this reason it forms the core method for popular autonomous control systems like the Ardupilot. The PID controller is popular because it works in a very simple manner and does not require factoring in the physics of the dynamical system into the equations. However, it requires manual tuning of some constants by trial and error. Understanding how the PID controller works can help in performing this tuning effectively.

Theory

This section provides a simple explanation of how a PID controller works. The equation for a PID controller is:

PIDController Equation.png

In this equation, {\mathrm  {u}} is the 'output signal'; the value we will apply to the control actuator in the UAV. For example, if we want to control the forward flight speed of an airplane, {\mathrm  {u}} would be the throttle setting. The variable {e} is called the error, and it is the difference between the desired value and the actual value. For example, if we want the airplane to fly at 50 mph but it is currently flying at 70 mph the error would be -20. The {\mathrm  {u}} value is simply a sum of three terms called the proportional, integral and differential terms. Each term has a positive constant K that must be manually tweaked for the controller to work as desired, multiplied by some function of the error.


Proportional Term

The proportional term adjusts the control signal based on the magnitude of the error at present time. This means that the larger the error at any instant, the greater the control signal that is applied at that instant. In the airplane speed example, if we are flying at 30 mph but our goal is 50 mph, the error would be 20, and the proportional term would add 20*K_{p} to the output signal, effectively increasing the throttle. The slower we are flying relative to the goal of 50 mph the higher the applied throttle, and the faster we are flying over 50 mph the lower the applied throttle. Although this may seem to be enough to make the controller work, in the Tuning section it will become apparent why the integral and proportional terms are often times necessary.

Integral Term

The integral term adjusts the control signal proportionally to the magnitude of accumulated error over past times. The more error that has accumulated, the higher the control signal that is applied. Note that negative error can cancel positive error. In the airplane speed example, if we have been flying at 30 mph for 12 seconds, while the goal is 50 mph, the accumulated error would be (50-30)*12=240, and we would add 240*K_{{i}} to the output signal, effectively increasing the throttle. The more time we spend below our goal, the more throttle will be applied. While the proportional term adjusts the output based on the present error, the integral term adjust the output based on past errors.

Differential Term

The differential term adjusts the control signal proportionally to the rate of change of the error with respect to time, or how fast the error is changing. In the airplane speed example, if we are flying at 30 mph with a goal of 50 mph, our error is 20. If we are accelerating such that we are gaining 5 mph every second, the error is going down 5 every second, and the differential of the error with respect to time is -5. The PID would add -5*K_{{d}} to the output signal, reducing the throttle. The faster we are approaching our goal of 50 mph, the lower the throttle is going to be. This has the effect of slowing down our approach to the goal to avoid overshooting it. While the proportional term adjusts the output based on the present error, and the integral term based on the past error, the differential term adjusts the output based on a prediction of future error. Knowing how fast the error is changing tells you something about what the error is going to be in a future instant.


Tuning

We recommend you read the Theory section before continuing. The present section provides a demonstration of how each tuning constant affects the performance of the PID controller. Understanding how it works, and with some practice, you can become an expert at PID tuning. You can follow the demonstration steps and practice on your own using this online PID simulator.

Proportional Term

Example of PID behavior with proportional term only

Imagine we want our PID controller to make our airplane fly at 50 mph, starting from 25 mph. From the theory section explanation on the proportional term it might seem like the proportional term is enough for the controller to work. So we set K_{p} to some positive value, and set K_{{i}} and K_{{d}} to 0 so the integral an differential terms disappear. The aircraft would behave somewhat like on shown on the graph to the right; the aircraft speeds up and stabilizes at some higher speed, but it never gets to the goal of 50 mph. The reason this happens is because of drag and the way the proportional term works. If we were actually travelling at 50 mph, the output signal to the throttle would be (50-50)*K_{p}=0, because the error would be zero. The aircraft cannot fly at 50 mph with throttle at 0 because of drag, and therefore the velocity will stabilize somewhere under 50 mph, where the error is non-zero and some level of throttle is being applied. This steady, non-zero error is called the steady-state error. Therefore the proportional term is not enough to get us to our desired speed in this case.


Integral Term

Example of PID behavior with proportional and integral terms only

The goal of the integral term is to reduce the steady-state error to zero so we can reach the speed goal. The more time we spend with a positive error, the more throttle the integral term will apply, until we eventually get to our desired speed. The plot on the right shows the behavior of the aircraft if we set positive values to K_{p} and K_{{i}}, but keep K_{{d}} at zero. Now the aircraft actually gets to 50 mph, but it overshoots and oscillates before slowly stabilizing. The integral term will get you to the goal, but will probably overshoot it and induce oscillations.


Differential Term

Example of tuned PID behavior

The goal of the differential term is to dampen oscillations in the state, so we can get to our goal of 50 mph with minimal or no overshooting or oscillations. The plot to the right shows how the aircraft could behave if we set good values for all three constants.


In Practice

Tuning the three constants of a PID is more of an art than a science. If a constant is set too low, the UAV might respond in a sluggish way, and might not reach the desired state. If any constant is set too high the UAV might respond erratically or with high-pitched oscillations. The goal is to reach the point right before erratic behavior, where the aircraft can get to the desired state quickly but without overshooting or oscillations. Achieving this can be challenging, but keeping in mind the function of each constant helps in this process. We recommend you practice using this online PID simulator to get a feel of how each tuning constant works.

Which constants produce the desired behavior depends on the dynamics of the system being controlled. This means that if we tune our PID for an aircraft but then somehow modify its dynamics (for example by adding more payload mass or shifting the CG), the same set of constants might no longer work. Similarly, the tuning might work for one set of flight conditions, but not in other flight conditions. One of the challenges when tuning a PID controller is to select values that are robust to possible and unexpected changes in configuration and flight conditions.

Implementation

A PID controller is very simple to implement in code. The following is a pseudocode on how to implement a PID algorithm for controlling the speed of an airplane:

 #Note: Set dt to small value, tuning constants Kp, Ki and Kd to appropiate values, and goal_speed to the desired flight speed.
 previous_error = 0
 integral = 0
 while true{
   actual_speed = getGroundSpeed()
   error = goal_speed - actual_speed
   integral = integral + error*dt
   derivative = (error - previous_error)/dt
   output = Kp*error + Ki*integral + Kd*derivative
   previous_error = error
   setThrottleLevel(output)
   wait(dt)
}

External Resources