00001 /*************************************************************************** 00002 * Copyright (C) 2005 by Robot Group Leipzig * 00003 * martius@informatik.uni-leipzig.de * 00004 * fhesse@informatik.uni-leipzig.de * 00005 * der@informatik.uni-leipzig.de * 00006 * * 00007 * This program is free software; you can redistribute it and/or modify * 00008 * it under the terms of the GNU General Public License as published by * 00009 * the Free Software Foundation; either version 2 of the License, or * 00010 * (at your option) any later version. * 00011 * * 00012 * This program is distributed in the hope that it will be useful, * 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00015 * GNU General Public License for more details. * 00016 * * 00017 * You should have received a copy of the GNU General Public License * 00018 * along with this program; if not, write to the * 00019 * Free Software Foundation, Inc., * 00020 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 00021 * * 00022 * $Log: noisegenerator.h,v $ 00023 * Revision 1.5 2008/05/30 11:58:27 martius 00024 * use cmath instead of math.h 00025 * 00026 * Revision 1.4 2008/05/07 16:45:52 martius 00027 * code cosmetics and documentation 00028 * 00029 * Revision 1.3 2008/04/18 14:00:38 guettler 00030 * fixed compile bug (assert.h was not included) 00031 * 00032 * Revision 1.2 2008/04/17 14:54:45 martius 00033 * randomGen added, which is a random generator with long period and an 00034 * internal state. Each Agent has an instance and passed it to the controller 00035 * and the wiring. This is good for 00036 * a) repeatability on agent basis, 00037 * b) parallel execution as done in ode_robots 00038 * 00039 * Revision 1.1 2008/04/16 12:40:58 martius 00040 * moved to utils 00041 * 00042 * Revision 1.17 2007/12/07 10:58:02 der 00043 * NoiseGenerator: method signature of add and generate changed! 00044 * IMNS: added cfactor parameter 00045 * 00046 * Revision 1.16 2007/12/06 18:17:14 der 00047 * corrected WhiteNormalNoise. parameters are now min and max. 00048 * 00049 * Revision 1.15 2006/12/11 14:00:09 martius 00050 * colornoise is more colorful (tau = 0.5) 00051 * variance for colornoise is invariant of tau now 00052 * 00053 * Revision 1.14 2006/10/09 12:37:54 martius 00054 * variance was wrong since it was sigma (std deviation) 00055 * 00056 * Revision 1.13 2006/08/04 15:16:13 martius 00057 * documentation 00058 * 00059 * Revision 1.12 2006/07/14 12:23:59 martius 00060 * selforg becomes HEAD 00061 * 00062 * Revision 1.10.6.1 2005/11/22 14:55:21 martius 00063 * added math.h 00064 * 00065 * Revision 1.10 2005/10/06 17:07:16 martius 00066 * removed MAXINT 00067 * 00068 * Revision 1.9 2005/09/11 11:20:21 martius 00069 * virtual destructors 00070 * 00071 * Revision 1.8 2005/08/22 20:32:29 martius 00072 * sine noise has phaseShift 00073 * 00074 * Revision 1.7 2005/08/06 20:47:54 martius 00075 * Commented 00076 * 00077 * Revision 1.6 2005/08/03 20:31:40 martius 00078 * sinenoise 00079 * no random initialisation anymore 00080 * 00081 * Revision 1.5 2005/07/21 15:11:19 martius 00082 * normalised noise strength for colored noise 00083 * 00084 * Revision 1.4 2005/07/14 16:07:12 fhesse 00085 * cmath included 00086 * 00087 * Revision 1.3 2005/07/06 16:05:34 martius 00088 * noise generator is splitted into sub classes with a common interface 00089 * 00090 * Revision 1.2 2005/06/15 16:04:56 martius 00091 * de-templatified 00092 * * 00093 ***************************************************************************/ 00094 #ifndef __NOISEGENERATOR_H 00095 #define __NOISEGENERATOR_H 00096 00097 #include <stdlib.h> 00098 #include <time.h> 00099 #include <cmath> 00100 #include <assert.h> 00101 00102 #include "randomgenerator.h" 00103 00104 /** Interface and basic class for noise generator. 00105 It is suitable for single noise channels but also multidimensional noise. 00106 */ 00107 class NoiseGenerator{ 00108 public: 00109 NoiseGenerator() { 00110 dimension=0; 00111 randGen=0; 00112 }; 00113 00114 virtual ~NoiseGenerator(){} 00115 00116 /** initialization with the the given dimension for multidimensional noise 00117 @param dimension dimensionality of vectors to be used by add 00118 @param randGen pointer to a random generator. If zero a new one generated internally 00119 @see add() 00120 */ 00121 virtual void init(unsigned int dimension, RandGen* randGen=0) { 00122 this->dimension = dimension; 00123 if(randGen) this->randGen=randGen; 00124 else { 00125 this->randGen=new RandGen(); 00126 this->randGen->init(rand()); 00127 } 00128 }; 00129 00130 /** generate somehow distributed random number parameterized with min and max. 00131 valid only for ONE random number, use \ref add() for 00132 adding this kind of noise to several channels 00133 */ 00134 virtual double generate() = 0; 00135 00136 /** adds multidimensional noise to the value field. 00137 Generic implementation calls generate for each channel. 00138 Overload this if you need different behavior. 00139 @param value field where noise is added. Must have length dimension (\ref init()) 00140 */ 00141 virtual void add(double *value, double noiseStrength){ 00142 for (unsigned int i = 0; i < dimension; i++){ 00143 value[i]+=generate()*noiseStrength; 00144 } 00145 } 00146 00147 protected: 00148 //generates white (no averaging) uniformly distributed random number between "min" and "max" 00149 double uniform(double min=-0.1, double max=0.1){ 00150 assert(randGen); 00151 return( randGen->rand()*(max-min)+min); 00152 } 00153 //generates white uniformly distributed random number between in [0,1) 00154 double uniform01(){ 00155 assert(randGen); 00156 return randGen->rand(); 00157 } 00158 unsigned int dimension; 00159 RandGen* randGen; 00160 }; 00161 00162 /// generates white (no averaging) uniformly distributed random number between "min" and "max" 00163 class WhiteUniformNoise : public NoiseGenerator{ 00164 public: 00165 WhiteUniformNoise() {} 00166 virtual ~WhiteUniformNoise(){} 00167 virtual double generate() { 00168 return uniform(-1,1); 00169 }; 00170 00171 }; 00172 00173 /// generates white and normal distributed random numbers. p1: mean, p2: standard deviation 00174 /// new parameter definition: p1: min, p2: max. the mean and standard deviation are calculated by this values 00175 class WhiteNormalNoise : public NoiseGenerator{ 00176 public: 00177 WhiteNormalNoise(){} 00178 virtual ~WhiteNormalNoise(){} 00179 virtual double generate() { 00180 double x1=uniform01(); 00181 double x2=uniform01(); 00182 return( (sqrt(-2*log(x1)) *cos(2*M_PI*x2))); 00183 }; 00184 // original version 00185 // virtual double generate(double mean, double stddev) { 00186 // double x1=uniform(0, 1); 00187 // double x2=uniform(0, 1); 00188 // return( (sqrt(-2*log(x1)) *cos(2*M_PI*x2)) * stddev + mean) ; 00189 // } 00190 00191 }; 00192 00193 /// generated colored noise. This is obtained by using time average of uniform distributed noise. 00194 class ColorUniformNoise : public NoiseGenerator{ 00195 public: 00196 /** @param tau time averaging factor (1/window) 00197 (1: smoothing (white) 0.1: strong color, 0 no noise anymore 00198 */ 00199 ColorUniformNoise(double tau=0.05) 00200 : tau(tau){ 00201 sqrttau = sqrt(tau); 00202 mean1channel=0.0; 00203 mean=0; 00204 } 00205 virtual ~ColorUniformNoise(){ if(mean) free(mean);} 00206 virtual void init(unsigned int dimension, RandGen* randGen=0){ 00207 NoiseGenerator::init(dimension, randGen); 00208 mean = (double*)malloc(sizeof(double) * dimension); 00209 for (unsigned int i=0; i<dimension; i++){ 00210 mean[i]=0.0; 00211 } 00212 } 00213 00214 virtual double generate() { 00215 mean1channel+= sqrttau * uniform(-1, +1) - tau * mean1channel; 00216 return(mean1channel); 00217 } 00218 00219 /** adds multidimensional noise to the value field. 00220 @param value field where noise is added. Must have length dimension (\ref init()) 00221 @param min lower bound of interval 00222 @param max upper bound of interval 00223 */ 00224 virtual void add(double *value, double noiseStrength){ 00225 for (unsigned int i = 0; i < dimension; i++){ 00226 mean[i]+= sqrttau * uniform(-1, +1)*noiseStrength - tau * mean[i]; 00227 value[i]+=mean[i]; 00228 } 00229 } 00230 00231 protected: 00232 double tau; // smoothing paramter 00233 double sqrttau; // square root of smoothing parameter 00234 double* mean; 00235 double mean1channel; 00236 }; 00237 00238 /// like ColorUniformNoise but averaging over normal distributed noise instead. 00239 class ColorNormalNoise : public WhiteNormalNoise{ 00240 public: 00241 ColorNormalNoise(double tau=0.05) 00242 : tau(tau){ 00243 sqrttau = sqrt(tau); 00244 mean = 0; 00245 mean1channel=0.0; 00246 } 00247 00248 virtual ~ColorNormalNoise(){if(mean) free(mean);} 00249 00250 virtual void init(unsigned int dimension, RandGen* randGen=0){ 00251 WhiteNormalNoise::init(dimension, randGen); 00252 mean = (double*)malloc(sizeof(double) * dimension); 00253 for (unsigned int i=0; i<dimension; i++){ 00254 mean[i]=0.0; 00255 } 00256 } 00257 00258 virtual double generate() { //double stddev, double meanvalue) { 00259 mean1channel += sqrttau * WhiteNormalNoise::generate() - tau*mean1channel; 00260 return(mean1channel); 00261 } 00262 00263 virtual void add(double *value, double noiseStrength) { 00264 for (unsigned int i = 0; i < dimension; i++){ 00265 mean[i]+=sqrttau * WhiteNormalNoise::generate()*noiseStrength - tau*mean[i]; 00266 value[i]+=mean[i]; 00267 } 00268 } 00269 00270 protected: 00271 double tau; // smoothing paramter 00272 double sqrttau; // square root of smoothing parameter 00273 double* mean; 00274 double mean1channel; 00275 double factor; 00276 }; 00277 00278 /// Sine wave noise. Produces a 90 degree phase shifted sine wave or white noise 00279 class SineWhiteNoise : public NoiseGenerator{ 00280 public: 00281 /** @param omega anglerate 00282 @param amplitude amplitude of the sine wave in respect to the noise strength 00283 @param phaseShift phase shift between channels in rad 00284 @param channels number of channel for sine noise (and the rest get white noise) 00285 */ 00286 SineWhiteNoise(double omega, double amplitude, double phaseShift = M_PI/2, 00287 unsigned int channels = 0xFFFF) 00288 : omega(omega), amplitude(amplitude) 00289 , channels(channels), phaseShift(phaseShift){ 00290 t=0; 00291 } 00292 00293 virtual ~SineWhiteNoise(){} 00294 00295 virtual double generate() { 00296 t ++; 00297 return uniform(-1, 1) + sin(t*omega)*amplitude*2; 00298 } 00299 00300 /** adds multidimensional noise to the value field. 00301 @param value field where noise is added. Must have length dimension (\ref init()) 00302 */ 00303 virtual void add(double *value, double noiseStrength) { // min, double max){ 00304 00305 for (unsigned int i = 0; i < dimension; i++){ 00306 if(i < channels) 00307 value[i]+=sin(t*omega+i*phaseShift)*amplitude*2; 00308 value[i]+=uniform(-1, 1); 00309 } 00310 t ++; 00311 } 00312 void setOmega(double omega){ 00313 this->omega=omega; 00314 } 00315 void setPhaseShift(double phaseShift){ 00316 this->phaseShift=phaseShift; 00317 } 00318 00319 protected: 00320 long int t; // time 00321 double omega; // angle velocity 00322 double amplitude; // factor for noise strength 00323 unsigned int channels; // number of channels with sine 00324 double phaseShift; // phase shift 00325 00326 }; 00327 00328 00329 #endif 00330