00001 /********************************************************************* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2010, LABUST, UNIZG-FER 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * * Redistributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * * Redistributions in binary form must reproduce the above 00014 * copyright notice, this list of conditions and the following 00015 * disclaimer in the documentation and/or other materials provided 00016 * with the distribution. 00017 * * Neither the name of the LABUST nor the names of its 00018 * contributors may be used to endorse or promote products derived 00019 * from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00024 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00025 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00026 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00027 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00031 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 * POSSIBILITY OF SUCH DAMAGE. 00033 *********************************************************************/ 00034 #include <labust/control/PIFFController.h> 00035 #include <labust/math/NumberManipulation.hpp> 00036 #include <math.h> 00037 #include <ros/ros.h> 00038 00039 void PIFF_modelTune(PIDBase* self, 00040 const PT1Model* const model, 00041 float w, float a) 00042 { 00043 self->Kp = 2*w*model->alpha-model->beta; 00044 self->Kd = self->Kt = self->Tf = 0; 00045 self->Ki = model->alpha*w*w; 00046 00047 //The empirical parameter for overshoot ~5% 00048 self->b = a*self->Ki/(self->Kp*w); 00049 ROS_ERROR("b-value dyn: %f %f",self->b,w); 00050 //self->b = 1; 00051 00052 self->model.alpha = model->alpha; 00053 self->model.beta = model->beta; 00054 self->model.betaa = model->betaa; 00055 00056 self->w = w; 00057 } 00058 00059 void PIFF_tune(PIDBase* self, float w, float a) 00060 { 00061 self->Kp = 2*w; 00062 self->Ki = w*w; 00063 self->Kd = self->Kt = self->Tf = 0; 00064 //The empirical parameter for overshoot ~5% 00065 self->b = a*self->Ki/(self->Kp*w); 00066 //self->b = 1; 00067 ROS_ERROR("b-value kin: %f %f",self->b,w); 00068 00069 self->w = w; 00070 } 00071 00072 void PIFF_wffIdle(PIDBase* self, float Ts, float error, float perror, float ff) 00073 { 00074 self->lastError = error; 00075 self->lastPError = perror; 00076 self->lastRef = self->desired; 00077 self->lastFF = ff; 00078 self->lastState = self->state; 00079 self->internalState = self->Kp*perror; 00080 self->internalState += ff; 00081 self->I = self->track - self->internalState; 00082 self->output = self->internalState = self->track; 00083 } 00084 00085 //void PIFF_wffStep(PIDBase* self, float Ts, float error, float perror, float ff) 00086 //{ 00087 // //Perform windup test if automatic mode is enabled. 00088 // if (self->autoWindup == 1) 00089 // { 00090 // self->windup = (self->internalState > self->output) && (error>0); 00091 // self->windup = (self->windup) || 00092 // ((self->internalState < self->output) && (error<0)); 00093 // } 00094 // else 00095 // { 00096 // //Experimental 00097 // //self->windup = ((self->windup >0) && (error>0)) || 00098 // // ((self->windup <0) && (error<0)); 00099 // } 00100 // 00101 // //Proportional term 00102 // self->internalState += self->Kp*(error-self->lastError); 00103 // //Integral term 00104 // //Disabled if windup is in progress. 00105 // if (!self->windup) self->internalState += self->Ki*Ts*error; 00106 // //Derivative 00107 // // self->internalState += self->Kd*1/Ts*(error-2*self->lastError+self->llastError); 00108 // //Feed forward term 00109 // self->internalState += ff - self->lastFF; 00110 // //Set final output 00111 // self->output = self->internalState; 00112 // 00113 // if (self->autoWindup == 1) 00114 // { 00115 // self->output = sat(self->output,-self->outputLimit, self->outputLimit); 00116 // } 00117 // 00118 // self->llastError = self->lastError; 00119 // self->lastError = error; 00120 // self->lastRef = self->desired; 00121 // self->lastFF = ff; 00122 //} 00123 00124 void PIFF_wffStep(PIDBase* self, float Ts, float error, float perror, float ff) 00125 { 00126 //Perform windup test if automatic mode is enabled. 00127 if (self->autoWindup == 1) 00128 { 00129 //self->windup = (self->internalState > self->output) && (error>0); 00130 //self->windup = (self->windup) || 00131 // ((self->internalState < self->output) && (error<0)); 00132 //Set the wind-up sign for cascade controllers. 00134 self->track = self->output; 00135 self->windup = (self->internalState != self->track) && (error*self->track > 0); 00136 } 00137 else 00138 { 00139 //Experimental 00140 /*self->windup = ((self->extWindup > 0) && (error > 0)) || 00141 ((self->extWindup < 0) && (error < 0));*/ 00142 //Experimental 2 00143 self->windup = (self->extWindup && (error*self->output > 0)); 00144 } 00145 00146 //Backward recalculation 00147 if ((self->lastI != 0) && self->windup && self->useBackward) 00148 { 00149 //Calculate the proportional influence 00150 //float diff = self->track - self->internalState + self->lastI; 00151 //If the proportional part is already in windup remove the whole last integral 00152 //Otherwise recalculate the integral to be on the edge of windup 00153 //self->internalState -= ((diff*self->track <= 0)?self->lastI:(self->lastI - diff)); 00154 00155 //self->I = self->track - self->internalState; 00156 00157 } 00158 00159 if (self->windup && self->useBackward) 00160 { 00161 //Proportional difference 00162 float diff = self->track - self->output + self->lastI; 00163 //ROS_ERROR("Windup diff=%f track=%f output=%f", diff, self->track, self->output); 00164 //ROS_ERROR("Windup I=%f, lI = %f, lerror=%f, error=%f", self->I, self->lastI, self->lastError, error); 00165 //if ((diff*self->track <= 0) || (self->output*self->track <=0)) 00166 { 00167 //Unwind 00168 self->I -= self->lastI; 00169 //ROS_ERROR("Unwinding"); 00170 } 00171 /*else 00172 { 00173 //ROS_ERROR("Recalculating"); 00174 self->I -= self->lastI - diff; 00175 }*/ 00176 } 00177 00178 00179 00180 //Proportional term 00181 //self->internalState += self->Kp*(error-self->lastError); 00182 //self->internalState += self->Kp*(perror - self->lastPError); 00183 self->internalState = self->Kp*perror; 00184 //Integral term 00185 //Disabled if windup is in progress. 00186 //if (!self->windup) self->internalState += (self->lastI = self->Ki*Ts*error); 00187 //else self->lastI = 0; 00188 //Feed forward term 00189 //self->internalState += ff - self->lastFF; 00190 00191 00192 self->internalState += ff; 00193 00194 00195 00196 //if (!self->windup) self->I += (self->lastI = self->Ki*Ts*error); 00197 00198 /* 00199 if (self->windup && self->useBackward && self->lastI != 0) 00200 { 00201 //Proportional difference 00202 float pcontrib = self->internalState;//- self->I; 00203 ROS_ERROR("Windup diff=%f track=%f output=%f", pcontrib, self->track, self->internalState + self->I); 00204 ROS_ERROR("Windup I=%f, lI = %f, lerror=%f, error=%f", self->I, self->lastI, self->lastError, error); 00205 if (fabs(pcontrib) > fabs(self->track)) 00206 { 00207 //Unwind 00208 self->I -= self->lastI; 00209 ROS_ERROR("Unwinding"); 00210 } 00211 else 00212 { 00213 ROS_ERROR("Recalculating"); 00214 self->I -= self->lastI; 00215 self->I += self->track - 0.98*pcontrib; 00216 ROS_ERROR("New output: out=%f", self->internalState + self->I); 00217 } 00218 } 00219 */ 00220 00221 /*if (self->windup && self->useBackward && self->lastI != 0) 00222 { 00223 //Proportional difference 00224 float diff = self->track - self->internalState - self->I; 00225 ROS_ERROR("Windup diff=%f track=%f output=%f", diff, self->track, self->internalState + self->I); 00226 ROS_ERROR("Windup I=%f, lI = %f, lerror=%f, error=%f", self->I, self->lastI, self->lastError, error); 00227 // if ((diff*self->track < 0) )//|| (self->output*self->track <=0)) 00228 { 00229 //Unwind 00230 //self->I -= self->lastI; 00231 //ROS_ERROR("Unwinding"); 00232 } 00233 // else 00234 { 00235 ROS_ERROR("Recalculating"); 00236 self->I -= -diff + 0*0.98*self->Ki*Ts*error; 00237 //ROS_ERROR("New output: out=%f", self->internalState + self->I); 00238 } 00239 } 00240 */ 00241 00242 //self->I += self->lastI = self->Ki*Ts*error; 00243 if (!self->windup) self->I += self->lastI = self->Ki*Ts*error; 00244 else self->lastI=0 ; 00245 self->internalState += self->I; 00246 00247 //Set final output 00248 self->output = self->internalState; 00249 00250 //ROS_ERROR("I: %f, P: %f, ff: %f", self->I, self->Kp*perror, ff); 00251 00252 if (self->autoWindup == 1) 00253 { 00254 self->output = sat(self->output,-self->outputLimit, self->outputLimit); 00255 } 00256 00257 self->lastError = error; 00258 self->lastPError = perror; 00259 self->lastRef = self->desired; 00260 self->lastFF = ff; 00261 self->lastState = self->state; 00262 } 00263