2010-09-24, 01:54 AM
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:
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:
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.
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.