proportional-integral-derivative controller (PID controller) help
Hi, i'd like to ask if you can post some pseudo-code to show how a PID controller work. Thanks.
Oh those are fun!
I use them a lot in my games...
spaceship thruster controls and whatnot
heres mine:
so with mine, i have it contained as a class.
and the P,I and D parameters are inputted in the constructor
then the Setpoint is stored externally by your program (it changes a lot so i dont bother having it be inside the PID itself)
so every gameloop i call checkpid, sending it the Input and the Setpoint, and it returns a float for me to use in the game
actually calculating good P,I, and D values is something you need to do yourself of course... I just tweak them by hand
I use them a lot in my games...
spaceship thruster controls and whatnot
heres mine:
class pidcontroller{ float integral; float lasterror; float P,I,D;public: pidcontroller(float p,float i, float d){ P=p;I=i;D=d; integral=0; lasterror=0; } float checkpid(float input,float setpoint){ float error=setpoint-input; integral+=error; float derivative=error-lasterror; lasterror=error; //printf("e%f i%f d%f\n",error,integral,derivative); return ((P*error)+(I*integral)+(D*derivative)); }};
so with mine, i have it contained as a class.
and the P,I and D parameters are inputted in the constructor
then the Setpoint is stored externally by your program (it changes a lot so i dont bother having it be inside the PID itself)
so every gameloop i call checkpid, sending it the Input and the Setpoint, and it returns a float for me to use in the game
actually calculating good P,I, and D values is something you need to do yourself of course... I just tweak them by hand
Thank you very much for your help ! I bet finding the most accurate P,I and D values must be quite time-consuming, right ?
What i need is to use a PID controller to command aircraft elevators so that altitude is mantained say at 10,000 feet.
What P,I,D values could i use just to start experimenting ?
Thanks again.
What i need is to use a PID controller to command aircraft elevators so that altitude is mantained say at 10,000 feet.
What P,I,D values could i use just to start experimenting ?
Thanks again.
Quote:Original post by Alessandro
Thank you very much for your help ! I bet finding the most accurate P,I and D values must be quite time-consuming, right ?
What i need is to use a PID controller to command aircraft elevators so that altitude is mantained say at 10,000 feet.
What P,I,D values could i use just to start experimenting ?
Thanks again.
be careful here: a PID, while not limited to, is designed mostly for second order systems, and i quite doubt a transferfunction from rudders to height is anything like second order.
Just for comparison, here is my PID controller class:
It is based on the information in this page: sci.engr.* FAQ on PID Controller Tuning
class PIDController{public: /// Constructor PIDController( float kp, float ki, float kd ); /// Updates the controller. void Update( float sv, float pv, float dt ); /// Returns the current control value. float GetControlValue() const { return m_ControlValue; }private: float m_ControlValue; float m_P; float m_I; float m_D; float m_E0, m_E1, m_E2;}; /// @param kp P parameter./// @param ki I parameter./// @param kd D parameter.PIDController::PIDController( float kp, float ki, float kd ) : m_P( kp ), m_I( ki ), m_D( kd ){ m_E0 = 0.f; m_E1 = 0.f; m_E2 = 0.f; m_ControlValue = 0.f;} /// @param sv Set value. This is the target value./// @param pv Process value. This is the measured (or current) value./// @param dt The time elapsed since the last update.void PIDController::Update( float sv, float pv, float dt ){ // If the elapsed time is zero (or less) ignore this update. if ( dt <= 0.f ) { return; } // Only the last 3 error values are needed. m_E2 = m_E1; m_E1 = m_E0; m_E0 = sv - pv; float const e01 = m_E0 - m_E1; float const e12 = m_E1 - m_E2; float const p = m_P * e01; float const i = m_I * m_E0 * dt; float const d = m_D * ( e01 - e12 ) / dt; m_ControlValue += p + i + d; }
It is based on the information in this page: sci.engr.* FAQ on PID Controller Tuning
*looks at JohnBolton's PID*
*remembers important point*
Alessandro:
My PID is designed under the assumption that it be updated every gameloop, and that the gameloop has a Constant update frequency.
If you are dependant on screen framerate for your game update (that's bad practice BTW) it will mess mine up.
if thats the case, notice how JohnBolton's takes time as an additional argument, so it can compensate for variable timings
*remembers important point*
Alessandro:
My PID is designed under the assumption that it be updated every gameloop, and that the gameloop has a Constant update frequency.
If you are dependant on screen framerate for your game update (that's bad practice BTW) it will mess mine up.
if thats the case, notice how JohnBolton's takes time as an additional argument, so it can compensate for variable timings
I have to confess that I had never heard of PID controllers. However, it is fairly clear that this is just a particular subclass of linear filters, where the coefficients of datapoints in the past have all constant weight, except for the current one and the previous (well, I guess you could estimate the derivative using more than two points, but let's ignore that).
Wouldn't it be better for most situations to have some kind of downweighting of things that happened too long ago? In haphazardlynamed's code, that would mean replacing the line
integral+=error;
by
integral = integral*.99 + error;
or something of that style.
Wouldn't it be better for most situations to have some kind of downweighting of things that happened too long ago? In haphazardlynamed's code, that would mean replacing the line
integral+=error;
by
integral = integral*.99 + error;
or something of that style.
Yes, some PIDs do that,
another common approach is to just cap the min and max values for Integral to avoid having it oversaturate with time.
I typically have the 'I' parameter as 0 anyway though, since I'm usually using it as a filter for user input vs thruster controls and stuff, where things change a lot and having an Integral parameter that tries to zero it at some constant point is bad...
another common approach is to just cap the min and max values for Integral to avoid having it oversaturate with time.
I typically have the 'I' parameter as 0 anyway though, since I'm usually using it as a filter for user input vs thruster controls and stuff, where things change a lot and having an Integral parameter that tries to zero it at some constant point is bad...
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement