00001
00002
00003
00004
00006
00007
00008 #include "../truckd/hw_interface.h"
00009 #include <math.h>
00010 #include <unistd.h>
00011 #include <fstream>
00012 #include <iostream>
00013 #include <signal.h>
00014 #include <sys/time.h>
00015 #include <errno.h>
00016
00017 using namespace std;
00018
00019 int quit=0;
00020
00021
00022
00023
00024 void sighandler(int signum) {
00025 if (signum == SIGINT) {
00026 if (!quit) {
00027 cerr << "caught ctrl-C quitting" << endl;
00028 quit = 1;
00029 } else {
00030 cerr << "second ctrl-C forcing exit" << endl;
00031 exit (EXIT_FAILURE);
00032 }
00033 } else {
00034 cerr << "caught unknown signal?" << endl;
00035 }
00036 }
00037
00038
00039 int getTime(struct timeval &time) {
00040 if (gettimeofday(&time,NULL) == -1) {
00041 cerr << "error with gettimeofday : " << strerror(errno) << endl;
00042 return -1;
00043 }
00044 return 0;
00045 }
00046
00047
00048 int timeDiffMS(struct timeval now, struct timeval old) {
00049 return (now.tv_sec - old.tv_sec) * 1000 + (now.tv_usec - old.tv_usec) / 1000;
00050 }
00051
00052
00053 int main(int argc, char *argv[]) {
00054
00055
00056 if ((argc != 5) && (argc != 6)) {
00057 cout <<
00058 "desc : produces a sine wave input to the motor controller,\n"
00059 " measures motor response, and saves data to a file\n"
00060 "usage : freqresp <options> freq P2Pamp DCoff\n"
00061 " freq = frequecy of input sine wave (should be < 1HZ)\n"
00062 " P2Pamp = peak to peak amplitude of input sine wave\n"
00063 " DCoff = average value (DC offset) of sine wave output\n"
00064 " options = -f <file> ; -t <time>\n"
00065 " file = file to save data too (default = /tmp/freqresp.dat\n"
00066 " time = number of seconds to run test for (default = 100 seconds)\n";
00067 return -1;
00068 }
00069
00070 char *filename = "/tmp/freqresp.dat";
00071 float runTime = 100;
00072
00073
00074 while(1) {
00075 opterr = 0;
00076 int opt = getopt(argc,argv,":t:f:");
00077
00078 if (opt == -1)
00079 break;
00080
00081 switch (opt) {
00082 case 'f':
00083 filename = optarg;
00084 break;
00085 case 't':
00086 if (sscanf(optarg,"%f", &runTime) != 1) {
00087 cerr << "can't convert '" << optarg << "' to number" << endl;
00088 return -1;
00089 }
00090 break;
00091 case '?':
00092 cerr << "unknown option '" << (char) optopt << "'" << endl;
00093 return -1;
00094 case ':':
00095 cerr << "missing argument for -" << (char) optopt << endl;
00096 return -1;
00097 default:
00098 cerr << "weight getopt result?" << endl;
00099 return -1;
00100 }
00101 }
00102
00103 ofstream data(filename);
00104 if (!data) {
00105 cerr << "error openning file '" << filename << "'" << endl;
00106 return -1;
00107 }
00108
00109 float freq, p2p, dc_off;
00110
00111
00112 if (sscanf(argv[optind], "%f",&freq) != 1) {
00113 cerr << "error : '" << argv[optind] << "' is not a number" << endl;
00114 return -1;
00115 }
00116 if (sscanf(argv[optind+1], "%f",&p2p) != 1) {
00117 cerr << "error : '" << argv[optind+1] << "' is not a number" << endl;
00118 return -1;
00119 }
00120 if (sscanf(argv[optind+2], "%f",&dc_off) != 1) {
00121 cerr << "error : '" << argv[optind+2] << "' is not a number" << endl;
00122 return -1;
00123 }
00124
00125 cout << "running for " << runTime << " seconds" << endl;
00126 cout << "saving results to '" << filename << "'" << endl;
00127 cout << " running with fq=" << freq << " p2p=" << p2p << " off=" << dc_off << endl;
00128 data << "# running with fq=" << freq << " p2p=" << p2p << " off=" << dc_off << endl;
00129
00130
00131 hwInterface hw( 1 );
00132 hw.reset();
00133
00134
00135 if (signal(SIGINT,sighandler) == SIG_ERR) {
00136 cerr << "error installing signal handler" << endl;
00137 return -1;
00138 }
00139
00140
00141 float avgTickDelta = 0.0f;
00142 float avgTickDelta2 = 0.0f;
00143 float time = 0.0f;
00144 int cycleCount = 0;
00145 struct timeval startTime, currentTime;
00146 hw.readStatus();
00147 float oldTicks = (float) (hw.encTicks(0) + hw.encTicks(1) + hw.encTicks(2) + hw.encTicks(3));
00148 if (getTime(startTime))
00149 return -1;
00150
00151
00152 while ((!quit) && (time <= runTime)) {
00153 hw.readStatus();
00154
00155
00156 float ticks = (float) (hw.encTicks(0) + hw.encTicks(1) + hw.encTicks(2) + hw.encTicks(3));
00157 float tickDelta = ticks-oldTicks;
00158 oldTicks = ticks;
00159 avgTickDelta += tickDelta;
00160 avgTickDelta2 += tickDelta * tickDelta;
00161 ++cycleCount;
00162
00163
00164 float power = dc_off + 0.5f * p2p * sinf(2.0f * M_PI * time * freq);
00165 hw.setSCPower(power);
00166 hw.writeControl();
00167
00168
00169 if (getTime(currentTime))
00170 break;
00171 data << timeDiffMS(currentTime,startTime) << '\t'
00172 << time << '\t'
00173 << power << '\t'
00174 << tickDelta << endl;
00175 time += 0.100;
00176
00177
00178 for (int i=0; i<10; ++i)
00179 hw.wait();
00180 }
00181
00182
00183 if (cycleCount > 0) {
00184 avgTickDelta /= (float) cycleCount;
00185 avgTickDelta2 /= (float) cycleCount;
00186 }
00187
00188 data << "# Ran for " << time << " seconds : "
00189 << "tick delta : average=" << avgTickDelta
00190 << " stdev=" << sqrtf(avgTickDelta2 - avgTickDelta*avgTickDelta) << endl;
00191
00192 cout << " E(X^2) = " << avgTickDelta2 << endl;
00193 cout << "Ran for " << time << " seconds : "
00194 << "tick delta : average=" << avgTickDelta
00195 << " stdev=" << sqrtf(avgTickDelta2 - avgTickDelta*avgTickDelta) << endl;
00196
00197
00198 hw.setSCPower(0);
00199
00200 return 0;
00201 }
00202
00203
00204
00206
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253