MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/Essentials/MOOSUtilityLib/ScalarPID.cpp
Go to the documentation of this file.
00001 
00002 //
00003 //   MOOS - Mission Oriented Operating Suite 
00004 //  
00005 //   A suit of Applications and Libraries for Mobile Robotics Research 
00006 //   Copyright (C) 2001-2005 Massachusetts Institute of Technology and 
00007 //   Oxford University. 
00008 //    
00009 //   This software was written by Paul Newman at MIT 2001-2002 and Oxford 
00010 //   University 2003-2005. email: pnewman@robots.ox.ac.uk. 
00011 //      
00012 //   This file is part of a  MOOS Core Component. 
00013 //        
00014 //   This program is free software; you can redistribute it and/or 
00015 //   modify it under the terms of the GNU General Public License as 
00016 //   published by the Free Software Foundation; either version 2 of the 
00017 //   License, or (at your option) any later version. 
00018 //          
00019 //   This program is distributed in the hope that it will be useful, 
00020 //   but WITHOUT ANY WARRANTY; without even the implied warranty of 
00021 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
00022 //   General Public License for more details. 
00023 //            
00024 //   You should have received a copy of the GNU General Public License 
00025 //   along with this program; if not, write to the Free Software 
00026 //   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 
00027 //   02111-1307, USA. 
00028 //
00030 // ScalarPID.cpp: implementation of the CScalarPID class.
00031 //
00033 
00034 #include <MOOSGenLib/MOOSGenLibGlobalHelper.h>
00035 #include "ScalarPID.h"
00036 #include <math.h>
00037 #include <iostream>
00038 #include <iomanip>
00039 using namespace std;
00040 
00042 // Construction/Destruction
00044 
00045 CScalarPID::CScalarPID()
00046 {
00047     m_dfKp  =   0;
00048     m_dfKd  =   0;
00049     m_dfKi  =   0;
00050     m_dfe   =   0;
00051     m_dfeSum =  0;
00052     m_dfeOld =  0;
00053     m_dfeDiff = 0;
00054     m_dfDT =    0;
00055     m_dfOldTime =0;
00056     m_dfOut =   0;
00057     m_nIterations=0;
00058     m_dfIntegralLimit = 0;
00059     m_dfOutputLimit   = 0;
00060 
00061     m_nHistorySize = 10;
00062     m_dfGoal = 0;
00063 
00064 
00065 }
00066 
00067 
00068 CScalarPID::CScalarPID(double dfKp,
00069                        double dfKd,
00070                        double dfKi,
00071                        double dfIntegralLimit,
00072                        double dfOutputLimit)
00073 {
00074     m_dfKp      =   dfKp;
00075     m_dfKd      =   dfKd;
00076     m_dfKi      =   dfKi;
00077     m_dfeSum    =   0;
00078     m_dfeOld    =   0;
00079     m_dfeDiff   =   0;
00080     m_dfDT      =   0;
00081     m_dfOldTime =  0;
00082     m_dfe       =   0;
00083     m_dfOut     =   0;
00084 
00085     m_dfIntegralLimit = dfIntegralLimit;
00086     m_dfOutputLimit   = dfOutputLimit;
00087 
00088     m_nIterations=  0;
00089 
00090 
00091 }
00092 
00093 CScalarPID::~CScalarPID()
00094 {
00095 
00096 }
00097 
00098 bool CScalarPID::Run(double dfeIn, double dfErrorTime,double &dfOut)
00099 {
00100     m_dfe  = dfeIn;
00101     
00102     //figure out time increment...
00103     if(m_nIterations++!=0)
00104     {
00105         
00106         m_dfDT = dfErrorTime-m_dfOldTime;
00107 
00108         if(m_dfDT<0)
00109         {
00110             MOOSTrace("CScalarPID::Run() : negative or zero sample time\n");
00111             return false;
00112         }
00113         else if(m_dfDT ==0)
00114         {
00115             //nothing to do...
00116             dfOut = m_dfOut;
00117             Log();
00118             return true;
00119         }
00120 
00121         //figure out differntial
00122         double dfDiffNow = (dfeIn-m_dfeOld)/m_dfDT;
00123         m_DiffHistory.push_front(dfDiffNow);
00124         while(m_DiffHistory.size()>=m_nHistorySize)
00125         {
00126             m_DiffHistory.pop_back();
00127         }
00128         
00129         m_dfeDiff = 0;
00130         list<double>::iterator p;
00131         for(p = m_DiffHistory.begin();p!=m_DiffHistory.end();p++)
00132         {
00133             m_dfeDiff   += *p;   
00134         }
00135         m_dfeDiff/=m_DiffHistory.size();
00136     }
00137     else
00138     {
00139         //this is our first time through
00140         m_dfeDiff = 0;
00141     }
00142 
00143 
00144     if(m_dfKi>0)
00145     {
00146         //calculate integral term  
00147         m_dfeSum    +=  m_dfKi*m_dfe*m_dfDT;
00148 
00149         //prevent integral wind up...
00150         if(fabs(m_dfeSum)>=fabs(m_dfIntegralLimit))
00151         {
00152 
00153 
00154             int nSign = (int)(fabs(m_dfeSum)/m_dfeSum);
00155             m_dfeSum = nSign*fabs(m_dfIntegralLimit);
00156 
00157         
00158         }
00159     }
00160     else
00161     {
00162         m_dfeSum = 0;
00163     }
00164     //do pid control
00165     m_dfOut = m_dfKp*m_dfe+
00166               m_dfKd*m_dfeDiff+
00167               m_dfeSum; //note Ki is already in dfeSum
00168 
00169 
00170     //prevent saturation..
00171     if(fabs(m_dfOut)>=fabs(m_dfOutputLimit) )
00172     {        
00173         int nSign =(int)( fabs(m_dfOut)/m_dfOut);
00174         m_dfOut = nSign*fabs(m_dfOutputLimit);
00175     }
00176 
00177     //save old value..
00178     m_dfeOld    = m_dfe;
00179     m_dfOldTime = dfErrorTime;
00180 
00181 
00182     dfOut = m_dfOut;
00183 
00184     //do logging..
00185     Log();
00186 
00187     return true;
00188 }
00189 
00190 void CScalarPID::SetGains(double dfKp, double dfKd, double dfKi)
00191 {
00192     m_dfKp      =   dfKp;
00193     m_dfKd      =   dfKd;
00194     m_dfKi      =   dfKi;
00195 }
00196 
00197 void CScalarPID::SetLimits(double dfIntegralLimit, double dfOutputLimit)
00198 {
00199    m_dfIntegralLimit = dfIntegralLimit;
00200    m_dfOutputLimit   = dfOutputLimit;
00201 }
00202 
00203 bool CScalarPID::SetName(string sName)
00204 {
00205     m_sName = sName;
00206     return true;
00207 }
00208 
00209 bool CScalarPID::SetLog(bool bLog)
00210 {
00211     m_bLog = bLog;
00212     return true;
00213 }
00214 
00215 bool CScalarPID::Log()
00216 {
00217 
00218     int nWidth = 17;
00219     
00220     if(m_bLog)
00221     {
00222         if(!m_LogFile.is_open())
00223         {
00224             string sName = MOOSFormat("%s%s%s.pid",
00225                 m_sLogPath.c_str(),
00226                 m_sName.c_str(),
00227                 MOOSGetTimeStampString().c_str());
00228             m_LogFile.open(sName.c_str());
00229             if(!m_LogFile.is_open())
00230             {
00231                 m_bLog = false;
00232                 return false;
00233             }
00234 
00235             m_LogFile.setf(ios::left);
00236 
00237             m_LogFile<<"%% Kp = "<<m_dfKp<<endl;
00238             m_LogFile<<"%% Kd = "<<m_dfKd<<endl;
00239             m_LogFile<<"%% Ki = "<<m_dfKi<<endl;
00240             m_LogFile<<setw(20)<<"%T";
00241             m_LogFile<<setw(nWidth)<<"Kp";
00242             m_LogFile<<setw(nWidth)<<"Kd";
00243             m_LogFile<<setw(nWidth)<<"Ki";
00244             m_LogFile<<setw(nWidth)<<"DT";
00245             m_LogFile<<setw(nWidth)<<"Output";
00246             m_LogFile<<setw(nWidth)<<"InputError";
00247             m_LogFile<<setw(nWidth)<<"Kp*e";
00248             m_LogFile<<setw(nWidth)<<"Kd*de/dt";
00249             m_LogFile<<setw(nWidth)<<"Ki*int(e)";
00250             m_LogFile<<setw(nWidth)<<"Desired";
00251             m_LogFile<<setw(nWidth)<<"Actual"<<endl;
00252             
00253         }
00254 
00255            //do pid control
00256         //    m_dfOut = m_dfKp*m_dfe+
00257         //    m_dfKd*m_dfeDiff+
00258         //   m_dfKi*m_dfeSum;
00259         m_LogFile.setf(ios::left);
00260         m_LogFile<<setw(20)<<setprecision(12)<<m_dfOldTime<<' ';
00261         m_LogFile<<setprecision(5);
00262         m_LogFile<<setw(nWidth)<<m_dfKp<<' ';
00263         m_LogFile<<setw(nWidth)<<m_dfKd<<' ';
00264         m_LogFile<<setw(nWidth)<<m_dfKi<<' ';
00265         m_LogFile<<setw(nWidth)<<m_dfDT<<' ';
00266         m_LogFile<<setw(nWidth)<<m_dfOut<<' ';
00267         m_LogFile<<setw(nWidth)<<m_dfe<<' ';
00268         m_LogFile<<setw(nWidth)<<m_dfKp*m_dfe<<' ';
00269         m_LogFile<<setw(nWidth)<<m_dfKd*m_dfeDiff<<' ';
00270         m_LogFile<<setw(nWidth)<<m_dfeSum<<' '; //Ki is already in dfeSum
00271         m_LogFile<<setw(nWidth)<<m_dfGoal<<' '; 
00272         m_LogFile<<setw(nWidth)<<m_dfGoal-m_dfe<<' '; 
00273 
00274         m_LogFile<<endl;
00275 
00276     }
00277 
00278     m_LogFile.flush();
00279 
00280     return true;
00281 }
00282 
00283 bool CScalarPID::SetLogPath(string &sPath)
00284 {
00285     m_sLogPath = sPath;
00286     return true;
00287 }
00288 
00289 bool CScalarPID::SetGoal(double dfGoal)
00290 {
00291     m_dfGoal =dfGoal;
00292     return true;
00293 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines