MOOS 0.2375
|
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 }