pid.cpp

Go to the documentation of this file.
00001 /*
00002  * This file is part of Micole Architecture
00003  *
00004  * Copyright (C) 2007 Micole partners
00005  *
00006  * Micole Architecture is free software: you can redistribute it 
00007  * and/or modify it under the terms of the GNU Lesser General 
00008  * Public License as published by the Free Software Foundation, 
00009  * either version 3 of the License, or (at your option) any 
00010  * later version.
00011  *
00012  * Micole Architecture is distributed in the hope that it will be 
00013  * useful, * but WITHOUT ANY WARRANTY; without even the implied 
00014  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
00015  * PURPOSE.  See the GNU Lesser General Public License for more 
00016  * details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with Micole Architecture.  If not, see
00020  * <http://www.gnu.org/licenses/>.
00021  */
00022 
00023 #include "stdafx.h"
00024 /* 
00025 
00026      The contents of this file are subject to the Mozilla Public License
00027 
00028          Version 1.1 (the "License"); you may not use this file except in
00029      compliance with the License. You may obtain a copy of the License at
00030      http://www.mozilla.org/MPL/
00031 
00032      Software distributed under the License is distributed on an "AS IS"
00033      basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
00034      License for the specific language governing rights and limitations
00035      under the License.
00036 
00037      The Original Code is the PID trajectory playback library.
00038 
00039      The Initial Developers of the Original Code are Andrew Crossan (ac@dcs.gla.ac.uk) 
00040          and John Williamson (jhw@dcs.gla.ac.uk) from University of Glasgow.
00041          
00042      Portions created by Andrew Crossan and John Williamson are Copyright (C) 2006.
00043      All Rights Reserved.
00044 
00045      Contributor(s): ______________________________________.
00046 
00047 */
00048 
00049 
00050 #include "pid.h"
00051 #include <math.h>
00052 #include <stdlib.h>
00053 
00054 
00055 /* Initialize a new PID controller 
00056 
00057 p: proportional control gain
00058 i: integral control gain
00059 d: derivative control gain
00060 f: input filter (for deriv. estimation)
00061 out_filter: output filtering
00062 gain: overall gain
00063 sat_low: minimum saturation point
00064 sat_high: maximum_saturation point
00065 */
00066 control_state *init_state(double p, double i, double d, double f, 
00067                                                   double out_filter, double gain, 
00068                                                   double dead_zone, double sat_low, double sat_high)
00069 {
00070   control_state *state;
00071   state = (control_state *)calloc(sizeof(*state), 1);
00072   state->last_action = 0;
00073   state->p = state->i = state->d = state->filter = 0;
00074     state->soft_saturate = 0;
00075   state->soft_saturate_scale = 1.0;
00076   state->x = state->target_x = 0;
00077   state->sat_low = sat_low;
00078   state->sat_high = sat_high;
00079   state->gain = gain;
00080   state->cn_p = p;  
00081   state->cn_i = i; 
00082   state->cn_d = d;  
00083   state->cn_f = f; 
00084   state->offset = 0;
00085   state->dead_zone = dead_zone;
00086   state->out_filter = out_filter;
00087   state->input = NULL;
00088   state->output = NULL;
00089   state->float_in = 0;
00090   state->float_out = 0;
00091   state->saturate = 0;
00092   state->max_integrator = 0.0;
00093   state->integrator_decay = 1.0;
00094   state->integrator_max_decay = 1.0;
00095   state->max_change = 0;
00096   state->integrator_kill = 5;
00097   state->input_filter = 1.0;
00098   state->i_cap = 1e18;
00099   return state;
00100 }
00101 
00102 
00103 void set_integrator_cap(control_state *state, double cap)
00104 {
00105         state->i_cap = cap;
00106 }
00107 
00108 void set_integrator_kill(control_state *state, double kill)
00109 {
00110 
00111                 state->integrator_kill = kill;
00112 }
00113 
00114 
00115 void set_input_filter(control_state *state, double f)
00116 {
00117 
00118         state->input_filter = f;
00119 }
00120 
00121 /* Limit the change in control values to max_change */
00122 void set_rate_limiter(control_state *state, double max_change)
00123 {
00124         state->max_change = max_change;
00125 
00126 }
00127 
00128 /* Set PID controller DC offset */
00129 void set_dc(control_state *state, double dc)
00130 {
00131         state->offset = dc;
00132 }
00133 
00134 /* Clip a value to a given range */
00135 double clip(double x, double a, double b)
00136 {
00137         if(x<a)
00138                 x=a;
00139         if(x>b)
00140                 x=b;
00141         return x;
00142 }
00143 
00144 /* Limits the integrator. 
00145 I is multiplied by decay each time step
00146 When integrator reaches max_decay, 
00147 it is multiplied by max_decay instead
00148 */
00149 void set_integrator_decay(control_state *state, double max, double decay, double max_decay)
00150 {
00151         state->max_integrator = max;
00152         state->integrator_decay = decay;
00153         state->integrator_max_decay = max_decay;
00154 }
00155 
00156 /* Do PID control */
00157 double control(control_state *state, double x, double target)
00158 {
00159   double  filter, action;
00160 
00161 
00162   
00163   state->x = x;
00164   state->target_x = state->input_filter * target  + (1-state->input_filter) * state->target_x;
00165 
00166 
00167   if(fabs(x-target) > state->dead_zone)
00168   {
00169         state->p = state->target_x - state->x;
00170 
00171         if(state->max_change>0.0)
00172         {
00173         if(state->p > state->max_change)
00174                 state->p = state->max_change;
00175         if(state->p < -state->max_change)
00176                 state->p = -state->max_change;
00177         }
00178 
00179         filter = state->cn_f * state->p + (1-state->cn_f) * state->filter;
00180 
00181         if(fabs(state->p) < state->integrator_kill)
00182                 state->i = 0;
00183 
00184         state->i += state->p;
00185 
00186         state->i *= (state->i>state->max_integrator) ? state->integrator_max_decay : state->integrator_decay;
00187 
00188         if(state->i>fabs(state->i_cap))
00189         {
00190                         state->i = state->i_cap;
00191         }
00192 
00193         state->d = filter - state->filter;
00194         state->filter = filter;
00195         action = state->p * state->cn_p + state->cn_i * state->i + state->d * state->cn_d;
00196         action *= state->gain;
00197 
00198 
00199 
00200         action = (state->out_filter * action) + (1-state->out_filter) * state->last_action;
00201         action += state->offset;
00202 
00203         /* Apply soft limiting */
00204         if(state->soft_saturate)
00205                 action = ((1.0/(1.0+exp(-action * state->soft_saturate_scale))) ) * 
00206                                         (state->sat_high - state->sat_low) + state->sat_low;
00207 
00208         
00209 
00210         action = clip(action, state->sat_low, state->sat_high);
00211 
00212 
00213         if(action==state->sat_low || action==state->sat_high)
00214                   state->saturate = 1;
00215         else
00216                   state->saturate = 0;
00217 
00218         state->last_action = action;
00219   }
00220   else
00221   {
00222                 action = state->last_action;
00223   }
00224    return action;
00225 }
00226 
00227 
00228 
00229 /* Enable soft saturation with given scale; disables if scale = 0 */
00230 void set_soft_saturation(control_state *state, double scale)
00231 {
00232         if(scale==0)
00233                 state->soft_saturate = 0;
00234         else
00235                 {
00236                         state->soft_saturate = 1;
00237                         state->soft_saturate_scale = scale;
00238                 }
00239 }
00240 
00241 
00242 void reset_state(control_state *state)
00243 {
00244         state->i = 0;
00245         state->d = 0;
00246         state->p = 0;
00247         state->last_action = 0;
00248         state->filter = 0;
00249         //state->input_filter = 0;
00250 }

Generated on Tue Oct 16 17:10:43 2007 for Micole by  doxygen 1.4.7