I see many people still don't know this excellent and pretty simple method of stabilizing things, so I decided to write a tutorial about it.
What is it?
PID controller is a thing that lets you stabilize many different things. The most basic example is a prop hovering in place - you take its position, feed it to a PID controller, and the controller outputs a force that can be used to hold the prop in place.
How does it work?
A PID controller is used to make a quantity (like position) reach a target value (a target position). The first thing a PID controller does is to calculate the error. The error is just the difference between the target value and the current value, for example:
Having the error, PID generates three values based on it, that the letters "P", "I" and "D" stand for:Code:Error = TargetPos - E:pos()
- P - proportional term - it's just Number*Error, which means the greater the error, the greater the P term.
- I - integral term - this is more complicated. It's a value that comes from summing errors over time. Basically, the greater the error, the faster this value grows. For those of you familiar with calculus, it's just Error integrated over time.
- D - derivative term - value that measures the change of Error over time. In GMod it will usually be just delta of Error, or $Error in E2 - that is, if at one moment the error is Error1, and a while later it's Error2, then the D term will equal Error2-Error1. Sometimes it's good to divide it by change (or delta) of time. For those familiar with calculus, it's just derivative of Error over time.
P, I and D terms can be generated in E2 like that:
Gains describe influence of the terms on the output value. The greater the gain, the more influence on output will a term have. Gain equal to 0 makes a term equal to 0 too, so it will have no influence on the output at all then.Code:@inputs TargetPos:vector @persist T [ITerm Error]:vector runOnTick(1) T = curtime() Error = TargetPos - entity():pos() #calculate error #initialize gains GainP = SomeNumber GainI = SomeNumber GainD = SomeNumber PTerm = GainP * Error ITerm += GainI * Error * $T DTerm = GainD * $Error / $T
Now, when we have P, I and D terms, we can generate output - it's just sum of P, I and D terms:
More detailed description of the P, I, D termsCode:Out = PTerm + ITerm + DTerm
Ok, we know what are the P, I, D terms and how to calculate them, but... what do they do?
P term can be thought of like that: when you use the PID controller to hold a prop in position, P term makes the force grow with distance from target. The further away from target the prop is, the stronger it is pushed towards the target. When it is exactly in place, the P term is 0, so it isn't pushed at all. Great!
But... When the prop was far away, it was pushed towards the target all the time along its way to the target. So, when it reaches the desired position, the force is 0, but it has a nonzero velocity... Simply put, it is still flying quite fast, so it will miss the target, turn around at some place and head to the target again... and again miss it. Here the D term comes to help!
The D term causes the prop to brake harder when it goes faster. This way, when the prop is going towards the target, the P term is pushing it to go faster, and the D term is pulling it away. At the target, when P term is 0, if the prop is still going fast, the D term is nonzero and causes it to brake. This way the prop will eventually stop at the target. The greater the D gain, the sooner it will happen. But be careful, too great D gain will cause the prop to go towards the target very slowly.
So, it seems like P and D terms can bring the prop to the target very well. Why do we need an I term then? Well, when we have gravity, the prop won't actually stop at the target, but a bit below it. Why? When the prop is floating without movement at the target, both P and D terms are 0, and yet the gravity is still pulling the prop down. The gravity force isn't countered by anything, so the prop will fall down... to the point where P term and gravity are in balance. You can make this effect smaller by increasing the P gain, but you will never get it exactly to the target this way.
The I term can fix this situation. When the prop floats below it's target, the error is nonzero, so the I term grows. It grows, and grows, and grows, to the point where error reaches 0. But this is exactly what we wanted, error 0 means we are exactly at the target
I term cutoff
The growing property of I term can be a trouble sometimes. If we start very far from our destination, the error is big and the I term grows very fast. It can become so big, that the prop will fly off into space before it can stabilize. Usually I term is used only to correct small errors that P and D alone can't fix - that's why I term is often calculated only when P term or D term are low enough, that is, it is "cut off" when P and D are too big.
It can be done for example like this:
Summary - perfect position stabilizing E2Code:PTerm = GainP * Error DTerm = GainD * $Error / $T if(PTerm:length() < 10 & DTerm:length() < 10) { ITerm += GainI * Error * $T } else { ITerm = vec() #make I term equal to 0 when P and D terms are too big }
Time to put all the knowledge from this tutorial together and make a perfect stabilizing E2.
I hope that now you understand how PID works and how to make your own self-stabilizing contraptionsCode:@name Position Stabilizing @inputs TargetPos:vector E:entity @persist T [ITerm Error]:vector @persist GainP GainI GainD #TargetPos is the position we want to hold prop E at runOnTick(1) if(first()) { ITerm = vec() #those are the values that worked for me - adjust them, if they don't work for you GainP = 5 GainD = 1 GainI = 4 } #this will let us calculate DeltaT ($T) T = curtime() #calculate error Error = TargetPos - E:pos() #calculate P and D terms PTerm = GainP*Error DTerm = GainD*$Error/$T #use I cutoff if(PTerm:length()<50 & DTerm:length()<10) { ITerm += GainI * Error * $T } else { ITerm = vec() } #calculate PID output Out = PTerm + ITerm + DTerm #apply force E:applyForce(Out*E:mass())![]()


LinkBack URL
About LinkBacks








Reply With Quote








in fact have a whole batch.
Bookmarks