MyBB Community Forums

Full Version: PID Algorithm and anti-windup
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Hello,

I'm looking to see if there may be any math or computer science majors here that would be able to help me with this.

As apart of my college studies and some of my own off the books research I've had the ability to play with the PID Algorithm for the past few years in applications such as robotics.

Recently, I've come back to the algorithm in my studies and through research I've been seeing a lot of discussion on the fact that the integrator can windup and cause the system to oscillate out of control very quickly.

Currently the industry standard solution is to implement an anti-windup system as defined:

 if (command_signal > min_output .AND. command_signal < max_output) 
  error_I = error_I + (set_point - actual)

In math terms: sum(error) when min < f(x) < max

Simply, it gives the command signal an "allowable range" to operate within and when it goes outside that range, then the integral part simply pauses until the command signal is back in range.

This works really well in a control system where, for instance, there is a valve on a water distribution plant and it runs accurately and steadily.

However, in an application where first and foremost the actual input is noisy and jumpy, for instance a traction control system in a high performance car or a competition robot, then we run into problems. We can state that the actual input coming from a specified source (an encoder for example) is defined as f(x) = Ax +/- Nx where Ax is the correct instantaneous measurement in real life and Nx is the noise in the signal generated from other forces that cause the resulting signal to offset. All of this means is that noise over a long period of time can cause the integrator to become permanently off track until it is rebooted thus resetting the integrator.

I'm thinking of an alternative implement of an anti-windup scheme in this algorithm could be instead of summing from start to infinity, instead only sum a rolling history of the last 5000 milliseconds (5 seconds) for instance. In applications such as cars we really don't care what happened two hours ago that would have thrown off the integral system, we just care about what happened recently and how to compensate for that.

I've been thinking about this and writing my own PID implementation with this alternative form of the anti-windup scheme and I'm wondering what other math or computer science majors here think of this? Maybe there is a pitfall or something I didn't realize when considering this form of implementation? I'm hoping to implement this soon and test it out on some prototypes to see the effects.

Edit: In case anyone is confused as to what the PID algorithm does I've written it in PHP:

class PID {

	private $lastMicrotime = 0;
	private $deltaTime = 0;
	
	private $integral = 0;
	
	private $errorPrevious = 0;
	
	private $setPoint = 0;
	private $errorCurrent = 0;
	private $Kp = 0;
	private $Ti = 0;
	private $Td = 0;
	private $min = 0;
	private $max = 0;
	
	public function __construct(float $setPoint, float $Kp, float $Ti, float $Td, float $min, float $max)
	{
		if($this->min >= $this->max)
		{
			return false;
		}
			
		$this->lastMicrotime = microtime(true);
		
		$this->setPoint = $setPoint;
		$this->Kp = $Kp;
		$this->Ti = $Ti;
		$this->Td = $Td;
		$this->min = $min;
		$this->max = $max;
	}
	
	/**
	 * This is considered the "Parallel" form of the PID Algorithm
	 */
	public function run(float $actual, $deltaTime=false)
	{
		$this->errorCurrent = ($this->setPoint - $actual);
		
		if($deltaTime !== false)
		{
			$this->deltaTime = $deltaTime;
		}
		else
		{
			$this->deltaTime = microtime(true) - $this->lastMicrotime;
			$this->lastMicrotime = microtime(true);
		}
		
		$proportional = $this->CalculateProportional();
		$integral = $this->CalculateIntegral();
		$derivative = $this->CalculateDerivative();
		
		return ($proportional+$integral+$derivative);
	}
	
	private function CalculateProportional()
	{
		return ($this->Kp * $this->errorCurrent);
	}
	
	private function CalculateIntegral()
	{
		if($this->Ti == 0)
		{
			return 0;
		}
		
		if(($this->integral >= $this->min) && ($this->integral <= $this->max))
		{
			$this->integral = (($this->deltaTime * $this->errorCurrent) / $this->Ti) + $this->integral;
		}
		
		return $this->integral;
	}
	
	private function CalculateDerivative()
	{
		if($this->Td == 0)
		{
			return 0;
		}
		
		$delta = (($this->Td / $this->deltaTime) * ($this->errorPrevious - $this->errorCurrent));
		$this->errorPrevious = $this->errorCurrent;
		
		return $delta;
	}
	
	public function setMinMax(float $min, float $max)
	{
		$this->min = $min;
		$this->max = $max;
	}
}

The PID loop is meant to be used in Real Time systems but sufficiently fast simulation can work just as well given proper physics are used.
Is there a simpler way to explain it?
Not really? This is mathematics all the way up to Calculus 2 concepts. Limits, derivatives, integrals etc. I could give a simple real-word example but it wouldn't really make you an expert, which is whom I am asking this question of.
If you, yourself who is a lead developer do not know what to do, then i don't think anyone here will.
(2010-10-01, 10:53 AM)dikidera Wrote: [ -> ]If you, yourself who is a lead developer do not know what to do, then i don't think anyone here will.

^this.
the issue is not with proper coding or Ryan's ability to code it. its about the mathematical functionality and logic behind the process in which he is developing.

This has nothing to do with MyBB or PHP.

(2010-10-01, 10:53 AM)dikidera Wrote: [ -> ]If you, yourself who is a lead developer do not know what to do, then i don't think anyone here will.

This is fail. Did you even read the post? I talked about the PID algorithm and one if it's shortcomings and then I offered a new theoretical way of implementing the integral for high-resolution based PID systems. My question to the community was of experts in computer science/mathematics who might be able to offer some feedback on this idea.
Unless you have other code to handle the case where the integral gets out of bounds, the integral will never be reset and just stay at the same value.
(2010-10-01, 06:38 PM)pavemen Wrote: [ -> ]Unless you have other code to handle the case where the integral gets out of bounds, the integral will never be reset and just stay at the same value.

Let me describe a real world scenario. Basically, when you have a traction control system implemented in cars, the point of the traction control system is to attempt to reach 20% slip during acceleration that would otherwise cause it to slip > 20% (between 15-20% slip is optimal based on studies) for the car to reach full acceleration in the shortest amount of time (the derivative of acceleration is called a "jerk", so we would want the most optimal "jerks" lol).

In real world tests it can be hard to see this effect on standard surfaces. Employing a surface called "regolith" (synthetically made moon dust; emulates the surface of the moon) which allows us to exaggerate the effects of slip because this type of surface has a low friction coefficient. Using this type of surface in my studies last year I was able to come up with a rough PID implementation but the integral constant would always wind-up over long periods of time (i.e. a two minute competition between the robots).

[attachment=20041]

You can see how well it works in a short time-frame although there was still a bit of overshoot and oscillation once the acceleration was released (that was 200 milliseconds that you see in that video, so 2 seconds). The problem was once I started running it for extended periods of time, the integral would windup and cause the drive system to do weird things (i.e., I could be pushing all the way forward at 100% on the joystick, but the integral would be at -100% so it would just stay at a speed of 0% and because this was within the setpoint, the PID algorithm would just "rest" at this because the algorithm thinks "this" is where it should stay to keep it within the setpoint.

If you wanted to see the actual algorithm I used for this then here it is in it's LabView implementation. I'm not sure how many people here know LabView as a programming language but maybe this will help.

[Image: 15939_208342928222_736043222_3928657_2579463_n.jpg]

So my theory is that instead of taking an infinite summation, it would be limited to say, the past 500 "error" readings. In this way, when I was pushing at 100% on the joystick the integral would expire quickly since the error was no longer building up and allow me to resume 100% speed quick enough but also still allow the integral to build up again if the slip went out of it's desired setpoint boundaries.
I understand the concept you are trying to implement and it makes sense to me. i am just commenting on the php code you posted where there is nothing to reset or re-evaluate the integral variable once it is out of bounds.

I can not read the LabView image, its too small

is the algorithm you are building getting reset upon RTC of the throttle or change in its output, or is it s simply being polled every so often? from my POV, the code you posted runs once and does not have a way to re-evaluate the integral value once/when it is out of bounds.

once i understand when the code you supplied will be used, then I may have more comment. However from my very limited knowledge in the area you are working, the basic logic appears fine. I just don't know how you use the return value of the run function or how often it is called.
Pages: 1 2