00001 #ifndef HOMEO2SERIAL_H
00002 #define HOMEO2SERIAL_H
00003
00004 #define _POSIX_SOURCE 1
00005 #include <fcntl.h>
00006 #include <termios.h>
00007 #include <unistd.h>
00008
00009 #include <fstream>
00010
00011 #include "output.h"
00012 #include "../microadam.h"
00013 #include "../microeva.h"
00014 #include "../../external/gnuplot/gnuplot.h"
00015
00016 extern "C"
00017 {
00018 #include <opencv/highgui.h>
00019 }
00020
00021 #define BAUDRATE B2400
00022 #define FALSE 0
00023 #define TRUE 1
00024
00025 namespace seemicro
00026 {
00027
00028 class Homeo2Serial : public OutputModule
00029 {
00030 Micro µ
00031
00032 Gnuplot<std::string> gs;
00033 Gnuplot<std::string> gs01;
00034
00045 static Homeo2Serial *home;
00046
00052 static const char TBNAME_C[], TBNAME_C0[];
00053
00057 struct termios oldtio;
00058
00062 int serialFd;
00063
00067 char buf[255];
00068
00072
00073
00077 float c, c0;
00078
00082 float epsilon, freqFaktor;
00083
00087 int iMittelAlpha, iMittelBeta, iEpsilon, ic, ic0, iGyroSkal, iFreqFaktor;
00088
00092 float lastAlpha, deltaAlpha, deltaAlphaGemittelt, lastBeta, betaGemittelt;
00093
00097 float gyro_skal;
00098
00099 public:
00100 Homeo2Serial(Micro& Am, string serialDevice = "/dev/ttyS0") :
00101 micro(Am)
00102 {
00103 home = this;
00104
00105
00106 c = 1.2;
00107 c0 = 0;
00108 epsilon = 0.1;
00109 freqFaktor = 1;
00110 gyro_skal = 2;
00111 setTrackbarVariables();
00112
00113 if(!gs.pipe || !gs01.pipe)
00114 {
00115 cerr << "Homeo2Serial: Failed gnuplot pipe initialization. Is gnuplot in your path?\n";
00116 }
00117 else
00118 {
00119 gs01.addChannel("deltaAlpha");
00120 gs01.addChannel("deltaAlphaGemittelt");
00121 gs.addChannel("c");
00122 gs.addChannel("c0");
00123 gs.addChannel("gyro_skal");
00124 gs.addChannel("freqFaktor");
00125 gs01.addChannel("mittelAlphaKoeff");
00126 gs01.addChannel("mittelBetaKoeff");
00127 gs01.addChannel("betaSkaliert");
00128 gs01.addChannel("mittelBeta");
00129 gs01.addChannel("epsilon");
00130 gs01.addChannel("toServo");
00131 }
00132
00133 cvNamedWindow("Homeo2Serial", 1);
00134
00135 iMittelAlpha = 500;
00136 cvCreateTrackbar("Mittelwertkoeffizient für alpha (0 .. 1)", "Homeo2Serial",
00137 &iMittelAlpha, 1000, callback);
00138 iMittelBeta = 500;
00139 cvCreateTrackbar("Mittelwertkoeffizient für beta (0 .. 1)", "Homeo2Serial",
00140 &iMittelBeta, 1000, callback);
00141 cvCreateTrackbar("Epsilon (1e-7 .. 1e3)", "Homeo2Serial", &iEpsilon, 1000, callback);
00142 cvCreateTrackbar(TBNAME_C, "Homeo2Serial", &ic, 2000, callback);
00143 cvCreateTrackbar(TBNAME_C0, "Homeo2Serial", &ic0, 2000, callback);
00144 cvCreateTrackbar("gyro_skal (-10 .. 10)", "Homeo2Serial", &iGyroSkal, 2000, callback);
00145 cvCreateTrackbar("freqFaktor (-100 bis 100)", "Homeo2Serial", &iFreqFaktor, 2000, callback);
00146
00147 struct termios newtio;
00148
00149
00150 if(DEBUGLEVEL>=2) cerr << "Opening serial device: '" << serialDevice << "'\n";
00151 serialFd = open(serialDevice.c_str(), O_RDWR | O_SYNC);
00152 if(serialFd < 0)
00153 {
00154 perror(serialDevice.c_str());
00155 exit(-1);
00156 }
00157
00158
00159 tcgetattr(serialFd, &oldtio);
00160
00161
00162 newtio.c_cflag = BAUDRATE | CS8 | CLOCAL;
00163 newtio.c_iflag = IGNPAR ;
00164 newtio.c_oflag = 0;
00165 newtio.c_lflag = 0;
00166 newtio.c_cc[VMIN]=1;
00167 newtio.c_cc[VTIME]=0;
00168 tcsetattr(serialFd, TCSANOW, &newtio);
00169 tcflush(serialFd, TCIFLUSH);
00170
00171 cvResizeWindow("Homeo2Serial", 300, 400);
00172 }
00173
00174 ~Homeo2Serial()
00175 {
00176 cvDestroyWindow("Homeo2Serial");
00177
00178
00179 if(DEBUGLEVEL>=2) cerr << "Resetting and closing serial port...";
00180 tcsetattr(serialFd, TCSANOW, &oldtio);
00181 close(serialFd);
00182 if(DEBUGLEVEL>=2) cerr << endl;
00183 }
00184
00185 void setTrackbarVariables()
00186 {
00187 iEpsilon = int( (log(epsilon)/log(10.)+7)*100 );
00188 ic = int(c*10)+1000;
00189 ic0 = int(c0*10)+1000;
00190 iGyroSkal = int(gyro_skal*100)+1000;
00191 iFreqFaktor = int(freqFaktor*10)+1000;
00192 }
00193
00194 void putTrackbarVariables()
00195 {
00196
00197 epsilon = pow(10., iEpsilon*0.01-7);
00198 c = (ic-1000)/10.;
00199 c0 = (ic0-1000)/10.;
00200 gyro_skal = (iGyroSkal-1000)/100.;
00201 freqFaktor = (iFreqFaktor-1000)/10.;
00202 }
00203
00204 float homeokinesis(float gyro_value, float beta, float alpha)
00205 {
00206 static float tt = 0;
00207
00208
00209 gyro_value = gyro_value*4/M_PI;
00210 if(gyro_value>1) gyro_value=1;
00211 if(gyro_value<-1) gyro_value=-1;
00212
00213
00214
00215 float y = 1.2*tanh(c*beta+c0) + 0.01 * sin(tt);
00216 c = c - epsilon*(2*y*y*c-1);
00217
00218 float epsQ = freqFaktor*epsilon*gyro_value*gyro_value+0.01;
00219 c0 = c0-(epsQ*y);
00220
00221 float sig = gyro_value*gyro_skal;
00222 y += sig;
00223
00224 if (y>1) y=1;
00225 if (y<-1) y=-1;
00226
00227 tt++;
00228 return y;
00229 }
00230
00231 void output(bool keyframe)
00232 {
00233 if(DEBUGLEVEL>2) cerr << "->Homeo2Serial::output\n";
00234 MicroAdam& adam = dynamic_cast<MicroAdam&>(micro);
00235
00236 deltaAlpha = micro.alpha - lastAlpha;
00237 lastAlpha = micro.alpha;
00238 if(deltaAlpha>=M_PI) deltaAlpha -= 2*M_PI;
00239 if(deltaAlpha<=-M_PI) deltaAlpha += 2*M_PI;
00240
00241 deltaAlphaGemittelt += iMittelAlpha*0.001*(deltaAlpha-deltaAlphaGemittelt);
00242
00243 betaGemittelt += iMittelBeta*0.001*(adam.beta-betaGemittelt);
00244
00245 float betaSkaliert = (betaGemittelt*180./M_PI/10.+0.25)/1.75;
00246 float toServo = homeokinesis(deltaAlphaGemittelt, betaSkaliert, micro.alpha);
00247
00248
00249 sprintf(buf, "%f\n", toServo);
00250 if(DEBUGLEVEL>=3)
00251 printf("\rdeltaAlpha=% 1.6f deltaAlphaGemittelt=% 1.4f toServo=% 1.4f",
00252 deltaAlpha, deltaAlphaGemittelt, toServo);
00253 write(serialFd, buf, strlen(buf));
00254
00255
00256 if(gs.pipe)
00257 {
00258 gs.putData("c", c);
00259 gs.putData("c0", c0);
00260 gs.putData("gyro_skal", gyro_skal);
00261
00262 gs.plot();
00263 }
00264
00265 if(gs01.pipe)
00266 {
00267
00268 gs01.putData("deltaAlphaGemittelt", deltaAlphaGemittelt);
00269 gs01.putData("mittelAlphaKoeff", iMittelAlpha/1000.);
00270 gs01.putData("mittelBetaKoeff", iMittelBeta/1000.);
00271
00272 gs01.putData("betaSkaliert", betaSkaliert);
00273 gs01.putData("epsilon", epsilon);
00274 gs01.putData("toServo", toServo);
00275 gs01.plot();
00276 }
00277
00278 if(!keyframe) return;
00279
00280 if(DEBUGLEVEL>=3) cerr << "Setting trackbars...";
00281 setTrackbarVariables();
00282 cvSetTrackbarPos(TBNAME_C, "Homeo2Serial", ic);
00283 cvSetTrackbarPos(TBNAME_C0, "Homeo2Serial", ic0);
00284 if(DEBUGLEVEL>=3) cerr << "OK\n";
00285 }
00286
00287 static void callback(int dummy)
00288 {
00289 if(!home) return;
00290 float epsilonAlt = home->epsilon;
00291 float gyroSkalAlt = home->gyro_skal;
00292 float freqAlt = home->freqFaktor;
00293
00294 home->putTrackbarVariables();
00295
00296 if(DEBUGLEVEL>=1 && epsilonAlt != home->epsilon)
00297 {
00298 cout << "epsilon=" << home->epsilon << endl;
00299 }
00300
00301 if(DEBUGLEVEL>=1 && gyroSkalAlt != home->gyro_skal)
00302 {
00303 cout << "gyro_skal=" << home->gyro_skal << endl;
00304 }
00305
00306 if(DEBUGLEVEL>=1 && freqAlt != home->freqFaktor)
00307 {
00308 cout << "freqFaktor=" << home->freqFaktor << endl;
00309 }
00310 }
00311
00312 bool loadParamsFromFile(string filename)
00313 {
00314 ifstream f(filename.c_str());
00315 if(!f.is_open()) return false;
00316 f >> c;
00317 f >> c0;
00318 f >> epsilon;
00319 f >> freqFaktor;
00320 f >> gyro_skal;
00321 f >> iMittelAlpha;
00322 f >> iMittelBeta;
00323 setTrackbarVariables();
00324 return true;
00325 }
00326
00327 bool saveParamsToFile(string filename)
00328 {
00329 ofstream f(filename.c_str());
00330 if(!f.is_open()) return false;
00331 f << c << endl;
00332 f << c0 << endl;
00333 f << epsilon << endl;
00334 f << freqFaktor << endl;
00335 f << gyro_skal << endl;
00336 f << iMittelAlpha << endl;
00337 f << iMittelBeta << endl;
00338 return true;
00339 }
00340
00341 };
00342
00343 }
00344
00345 #endif