00001 /** 00002 \file Robots/LoBot/misc/LoPID.H 00003 \brief Generic PID controller. 00004 00005 This file defines a class that implements a simple version of the 00006 standard PID control algorithm. 00007 */ 00008 00009 // //////////////////////////////////////////////////////////////////// // 00010 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00011 // by the University of Southern California (USC) and the iLab at USC. // 00012 // See http://iLab.usc.edu for information about this project. // 00013 // //////////////////////////////////////////////////////////////////// // 00014 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00015 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00016 // in Visual Environments, and Applications'' by Christof Koch and // 00017 // Laurent Itti, California Institute of Technology, 2001 (patent // 00018 // pending; application number 09/912,225 filed July 23, 2001; see // 00019 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00020 // //////////////////////////////////////////////////////////////////// // 00021 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00022 // // 00023 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00024 // redistribute it and/or modify it under the terms of the GNU General // 00025 // Public License as published by the Free Software Foundation; either // 00026 // version 2 of the License, or (at your option) any later version. // 00027 // // 00028 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00029 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00030 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00031 // PURPOSE. See the GNU General Public License for more details. // 00032 // // 00033 // You should have received a copy of the GNU General Public License // 00034 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00035 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00036 // Boston, MA 02111-1307 USA. // 00037 // //////////////////////////////////////////////////////////////////// // 00038 // 00039 // Primary maintainer for this file: mviswana usc edu 00040 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/LoBot/misc/LoPID.H $ 00041 // $Id: LoPID.H 13037 2010-03-23 01:00:53Z mviswana $ 00042 // 00043 00044 #ifndef LOBOT_PID_CONTROLLER_DOT_H 00045 #define LOBOT_PID_CONTROLLER_DOT_H 00046 00047 //------------------------------ HEADERS -------------------------------- 00048 00049 // lobot headers 00050 #include "Robots/LoBot/util/triple.hh" 00051 00052 //----------------------------- NAMESPACE ------------------------------- 00053 00054 namespace lobot { 00055 00056 //------------------------- CLASS DEFINITION ---------------------------- 00057 00058 /** 00059 \class lobot::PID 00060 \brief Simple implementation of a PID controller. 00061 00062 This class implements a generic PID controller that doesn't really 00063 know anything about the control variable. Rather, it simply computes a 00064 command given the current error by keeping track of the P, I and D 00065 components of a PID controller. 00066 00067 This class is defined as a template. However, it is really meant to be 00068 used only with numeric types. 00069 */ 00070 template<typename T> 00071 class PID { 00072 // Prevent copy and assignment 00073 PID(const PID&) ; 00074 PID& operator=(const PID&) ; 00075 00076 /// As its name indicates, a PID controller has three components, 00077 /// viz., P or propoptional, I or integral, and D or derivative. The P 00078 /// term is computed instantaneously (i.e., from the current input); 00079 /// however, the I and D terms are cumulative in nature. Thus, we need 00080 /// to keep track of the and I and D terms. 00081 T m_i, m_d ; 00082 00083 /// The controller needs to track the previous error so that it can 00084 /// compute the D term properly. 00085 T m_prev_error ; 00086 00087 /// Each component has its own gain. To turn a component off, simply 00088 /// set that particular gain to zero. 00089 T m_p_gain, m_i_gain, m_d_gain ; 00090 00091 public: 00092 /// Re/setting the gains. 00093 //@{ 00094 void p_gain(const T& g) {m_p_gain = g ;} 00095 void i_gain(const T& g) {m_i_gain = g ;} 00096 void d_gain(const T& g) {m_d_gain = g ;} 00097 void gains (const T& p, const T& i, const T& d) { 00098 p_gain(p) ; 00099 i_gain(i) ; 00100 d_gain(d) ; 00101 } 00102 void gains(const triple<T, T, T>& g) {gains(g.first, g.second, g.third) ;} 00103 //@} 00104 00105 /// Retrieving the current gains. 00106 //@{ 00107 T p_gain() const {return m_p_gain ;} 00108 T i_gain() const {return m_i_gain ;} 00109 T d_gain() const {return m_d_gain ;} 00110 triple<T, T, T> gains() const { 00111 return make_triple(p_gain(), i_gain(), d_gain()) ; 00112 } 00113 //@} 00114 00115 /// Initialization. Clients should supply the gains to be used. 00116 //@{ 00117 PID(const T& p_gain = T(0), const T& i_gain = T(0), const T& d_gain = T(0)) ; 00118 PID(const triple<T, T, T>& gains) ; 00119 //@} 00120 00121 /// This method returns the command to be applied given the current 00122 /// error. 00123 T cmd(const T& error) ; 00124 00125 /// Sometimes, clients may find it necessary to reset the controller 00126 /// and start over again. 00127 void reset() {m_i = m_d = 0 ; m_prev_error = 0 ;} 00128 00129 /// Clean-up. 00130 ~PID() ; 00131 } ; 00132 00133 //-------------------------- INITIALIZATION ----------------------------- 00134 00135 template<typename T> 00136 PID<T>::PID(const T& p_gain, const T& i_gain, const T& d_gain) 00137 : m_i(0), m_d(0), 00138 m_prev_error(0), 00139 m_p_gain(p_gain), m_i_gain(i_gain), m_d_gain(d_gain) 00140 {} 00141 00142 template<typename T> 00143 PID<T>::PID(const triple<T, T, T>& g) 00144 : m_i(0), m_d(0), 00145 m_prev_error(0), 00146 m_p_gain(g.first), m_i_gain(g.second), m_d_gain(g.third) 00147 {} 00148 00149 //------------------------- CONTROL ALGORITHM --------------------------- 00150 00151 template<typename T> 00152 T PID<T>::cmd(const T& error) 00153 { 00154 m_i += error ; 00155 m_d = (error - m_prev_error) ; 00156 T out = m_p_gain * error + m_i_gain * m_i + m_d_gain * m_d ; 00157 00158 m_prev_error = error ; 00159 00160 return out ; 00161 } 00162 00163 //----------------------------- CLEAN-UP -------------------------------- 00164 00165 template<typename T> 00166 PID<T>::~PID() 00167 {} 00168 00169 //----------------------------------------------------------------------- 00170 00171 } // end of namespace encapsulating this file's definitions 00172 00173 #endif 00174 00175 /* So things look consistent in everyone's emacs... */ 00176 /* Local Variables: */ 00177 /* indent-tabs-mode: nil */ 00178 /* End: */