00001 /*!@file Controllers/PID.C Encapsulation of PID */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Controllers/PID.C $ 00035 // $Id: PID.C 11533 2009-07-28 04:35:43Z lior $ 00036 // 00037 00038 #include "Controllers/PID.H" 00039 00040 //hack to adjust for buoyancy 00041 #define BUOYANCY_OFFSET 0 00042 00043 // ###################################################################### 00044 template <class T> 00045 PID<T>::PID(const float pGain, const float iGain, 00046 const float dGain, const T& iMin, const T& iMax, 00047 const T& errThresh, 00048 const T& posThresh, const T& negThresh, 00049 const T& maxMotor, const T& minMotor, 00050 const int noMoveThresh, 00051 const bool runPID, 00052 const float speed, 00053 const T& posStaticErrThresh, 00054 const T& negStaticErrThresh 00055 ) : 00056 itsIstate(0), itsDstate(0), 00057 itsPgain(pGain), itsIgain(iGain), itsDgain(dGain), 00058 itsImin(iMin), itsImax(iMax), 00059 itsErrThresh(errThresh), itsPosStaticErrThresh(posStaticErrThresh), 00060 itsNegStaticErrThresh(negStaticErrThresh), 00061 itsPosThresh(posThresh), itsNegThresh(negThresh), 00062 itsMaxMotor(maxMotor), itsMinMotor(minMotor) , 00063 itsNoMoveThresh(noMoveThresh), 00064 itsRunPID(runPID), 00065 itsSpeed(speed), 00066 itsNoMoveCount(0) 00067 00068 { } 00069 00070 // ###################################################################### 00071 template <class T> 00072 PID<T>::~PID() 00073 { } 00074 00075 // ###################################################################### 00076 template <class T> 00077 void PID<T>::setPIDPgain(float p) 00078 { 00079 itsPgain = p; 00080 } 00081 00082 template <class T> 00083 void PID<T>::setPIDIgain(float i) 00084 { 00085 itsIgain = i; 00086 } 00087 00088 template <class T> 00089 void PID<T>::setPIDDgain(float d) 00090 { 00091 itsDgain = d; 00092 } 00093 00094 template <class T> 00095 void PID<T>::setSpeed(float s) 00096 { 00097 itsSpeed = s; 00098 } 00099 00100 template <class T> 00101 void PID<T>::setPIDOn(bool val) 00102 { 00103 itsRunPID = val; 00104 itsNoMoveCount = 0; 00105 } 00106 00107 // ###################################################################### 00108 template <class T> 00109 T PID<T>::update(const T& target, const T& val) 00110 { 00111 // NOTE: we only use unary operators on T for compatibility with Angle... 00112 00113 itsVal = val; 00114 itsTarget = target; 00115 00116 if (!itsRunPID) return 0; 00117 00118 // compute the error: 00119 T err = target - val; 00120 itsErr = err; 00121 T pterm = err; pterm *= itsPgain; 00122 00123 // update the integral state: 00124 itsIstate += err; 00125 if (itsIstate > itsImax) itsIstate = itsImax; 00126 else if (itsIstate < itsImin) itsIstate = itsImin; 00127 T iterm = itsIstate; iterm *= itsIgain; 00128 00129 // update the derivative term: 00130 T diff = (val - itsDstate); 00131 itsVel = diff; 00132 itsDstate = val; 00133 T dterm = diff; dterm *= itsDgain; 00134 00135 // Command is just the P-I-D combination of the above: 00136 pterm += iterm; pterm -= dterm; 00137 00138 //process some non linear controls 00139 //if (itsErrThresh > 0) 00140 //{ 00141 // if (itsErr > itsPosStaticErrThresh || itsErr < itsNegStaticErrThresh) 00142 // { 00143 // if(itsVel != 0) 00144 // { 00145 // itsNoMoveCount = 0; 00146 // } 00147 // else 00148 // { 00149 // if (pterm != 0) 00150 // { 00151 // if (itsErr > 0) 00152 // pterm = itsPosThresh; 00153 // else 00154 // pterm = itsNegThresh; 00155 // } 00156 00157 // itsNoMoveCount++; 00158 // } 00159 // } 00160 // else 00161 // { 00162 // pterm = 0; 00163 // itsNoMoveCount = 0; 00164 // } 00165 //Over move Handling 00166 //TODO Fix it 00167 //if (itsNoMoveCount > itsNoMoveThresh) 00168 //{ 00169 // //Stop Motor 00170 // pterm = 0; 00171 // itsRunPID = false; 00172 //} 00173 //} 00174 00175 00176 if (pterm > itsSpeed) pterm = itsSpeed; 00177 if (pterm < -itsSpeed) pterm = -itsSpeed; 00178 00179 if (pterm > itsMaxMotor) pterm = itsMaxMotor; 00180 if (pterm < itsMinMotor) pterm = itsMinMotor; 00181 itsPTerm = pterm; 00182 00183 00184 return pterm; 00185 } 00186 00187 template <class T> 00188 T PID<T>::update(const T& targetPos, const T& targetVel, const T& currentVal) 00189 { 00190 // NOTE: we only use unary operators on T for compatibility with Angle... 00191 00192 00193 if (!itsRunPID) return 0; 00194 00195 // compute the error: 00196 T posErr = targetPos - currentVal; 00197 itsErr = posErr; 00198 00199 // update the integral state: 00200 //itsIstate += err; 00201 //if (itsIstate > itsImax) itsIstate = itsImax; 00202 //else if (itsIstate < itsImin) itsIstate = itsImin; 00203 //T iterm = itsIstate; iterm *= itsIgain; 00204 00205 // update the velocity term: 00206 00207 T vel = (currentVal - itsLastVal); 00208 T velErr = (targetVel - vel); 00209 00210 T pTerm = posErr; //To avoid angle multiplication 00211 pTerm *= itsPgain; 00212 00213 T dTerm = velErr; 00214 dTerm *= itsDgain; 00215 00216 T pid = pTerm + dTerm; 00217 00218 //if (fabs(velErr) > 0 && posErr > 0 && vel == 0 && pid < itsPosThresh) 00219 // pid = itsPosThresh; 00220 //else if (fabs(velErr) > 0 && posErr < 0 && vel == 0 && pid > itsNegThresh) 00221 // pid = itsNegThresh; 00222 00223 itsLastVal = currentVal; 00224 00225 00226 if (pid > itsMaxMotor) pid = itsMaxMotor; 00227 if (pid < itsMinMotor) pid = itsMinMotor; 00228 00229 return pid; 00230 } 00231 00232 // Instantiations: 00233 template class PID<float>; 00234 template class PID<Angle>; 00235 00236 // ###################################################################### 00237 /* So things look consistent in everyone's emacs... */ 00238 /* Local Variables: */ 00239 /* indent-tabs-mode: nil */ 00240 /* End: */