[ODE] Servo to reach a target position
David Whittaker
david at csworkbench.com
Thu Apr 10 15:26:02 2003
Doh! And here's the fix to my fix (change the division to multiplication).
> Noticed a bug.... see below (the fix:'s). Unless I'm really confused,
> you need to divide the Error by the timestep instead of a constant 10 in
> the CalcI function.
>
> Conceptually, it seems to me that the I calculation should only take
> into account the integral of the error over the past (N) seconds. As
> opposed to the total error since the dawn of time... But I could be
> wrong.
>
> David
>
>>>I'm be interested! Not so much for ODE, but because I tried to write
>>> one for an unrelated project and got nowhere. Ended up coming up
>>> with something that does work well, and fits what I thought PID
>>> meant, but actually looks nothing like what a later learned PID was.
>>> :-)
>>
>> Here's the code, tho I haven't had a chance to test it very
>> extensively. Be wary the I calculation may be wrong, but it works for
>> me :)
>>
>> Also remember, 95% of applications only need P, and 99% only need P
>> and D.
>>
>> // pid.h
>>
>> #ifndef PID_H
>> #define PID_H
>>
>> #include <math.h>
>>
>> class PID
>> {
>> // Kp = Proportional gain
>> // Ki = Integral gain
>> // Kd = Derivative gain
>> // Isum = accumulated error for I-term
>> // E = saved Error from previous calculation
>> // MaxE = maximum error signal seen
>> // dT1 = saved dT from previous calculation
>> // OV = Output Variable
>> float Kp, Ki, Kd, Isum, E, MaxE, dT1, OV;
>> public:
>> PID ( float Kp_=0, float Ki_=0, float Kd_=0 )
>> {
>> Reset();
>> SetGain ( Kp_, Ki_, Kd_ );
>> }
>>
>> void Reset()
>> {
>> Isum = 0;
>> E = 0;
>> dT1 = 0;
>> MaxE = 0;
>> OV = 0;
>> }
>>
>> void SetGain ( float Kp_, float Ki_=0, float Kd_=0 )
>> {
>> Kp = Kp_;
>> Ki = Ki_;
>> Kd = Kd_;
>> }
>>
>> // SP = destination/target
>> // PV = feedback
>> // dT = time elapsed since last update
>> // return value = command output
>> float StepPosition ( float SP, float PV, float dT )
>> {
>> float E1 = E; // previous error
>> E = SP - PV; // new error
>>
>> float Op=0, Oi=0, Od=0; // P, I, and D terms of calculation
>>
>> // P-Loop
>> Op = CalcP ( E );
>>
>> // I-Loop
>> Oi = CalcI ( E );
> fix: Oi = CalcI ( E, dT );
>>
>> // D-Loop
>> Od = CalcD ( E, E1 );
>>
>> // Final Summation
>> OV = Op + Oi + Od;
>>
>> dT1 = dT; // save this dT to be previous dT for next time
>>
>> return OV;
>> }
>>
>> // SP = destination/target
>> // PV = feedback
>> // dT = time elapsed since last update
>> // return value = command output
>> float StepSpeed ( float SP, float PV, float dT )
>> {
>> float E1 = E; // previous error
>> E = SP - PV; // new error
>>
>> float Op=0, Oi=0, Od=0; // P, I, and D terms of calculation
>>
>> // P-Loop
>> Op = CalcP ( E );
>>
>> // I-Loop
>> Oi = CalcI ( E );
> fix: Oi = CalcI ( E, dT );
>>
>> // D-Loop
>> Od = CalcD ( E, E1 );
>>
>> // Final Summation
>> OV += Op + Oi + Od;
>>
>> dT1 = dT; // save this dT to be previous dT for next time
>>
>> return OV;
>> }
>>
>> private:
>> float CalcP ( float E )
>> {
>> return E * Kp;
>> }
>>
>> float CalcI ( float E )
> fix: float CalcI ( float E, float dT )
>> {
>> if ( Ki > 0 )
>> {
>> Isum += E / 10;
> fix: Isum += E / dT;
fix:fix: Isum += E * dT;
>> if ( fabs(E) > MaxE )
>> MaxE = (float)fabs(E);
>> if ( Isum > MaxE )
>> Isum = MaxE;
>> else if ( Isum < -MaxE )
>> Isum = -MaxE;
>> return Ki * Isum;
>> }
>> else
>> return 0;
>> }
>>
>> float CalcD ( float E, float E1 )
>> {
>> if ( Kd > 0 )
>> {
>> float dE = E - E1; // change in error
>> return Kd * E;
>> }
>> else
>> return 0;
>> }
>> };
>>
>> #endif//PID_H
>>
>> // pidtest.cpp
>>
>> #include <stdio.h>
>> #include "../pid.h"
>>
>> void main()
>> {
>> PID pid ( 0.1f );
>> float position = 0;
>> for ( int i = 0; i < 50; i++ )
>> {
>> position += pid.StepPosition ( 10, position, 0.1f );
>> printf ( "%.02f ", position );
>> }
>> printf ( "\n\nfinal position: %.02f\n", position );
>> }
>>
>> // end of pidtest.cpp
>>
>> _______________________________________________
>> ODE mailing list
>> ODE@q12.org
>> http://q12.org/mailman/listinfo/ode
>
>
>
> _______________________________________________
> ODE mailing list
> ODE@q12.org
> http://q12.org/mailman/listinfo/ode