00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "uvsim/sensing/Imu6DofSensor.h"
00020 #include <iostream>
00021 #include <fstream>
00022 #include <cmath>
00023 #include <boost/numeric/ublas/vector.hpp>
00024 #include <boost/numeric/ublas/io.hpp>
00025 #include "uvsim/utilities/utilities.h"
00026
00027 using namespace boost::numeric::ublas;
00028
00029
00030 class Calibration
00031 {
00032 private:
00033 std::string device;
00034 int choice;
00035 double arm_length;
00036 std::string orientation;
00037 int cycle;
00038 int numCycles;
00039 vector<double>
00040 sum_mb, sum_fb, sum_wb,
00041 sumSq_mb, sumSq_fb, sumSq_wb,
00042 avg_mb, avg_fb, avg_wb,
00043 max_mb, min_mb, bias_mb, scale_mb,
00044 std_mb, std_fb, std_wb,
00045 freqCutMb, freqCutFb, freqCutWb;
00046 uvsim::Imu6DofSensor * imu;
00047 std::string notes, file, noteFileName, dataFileName;
00048 std::ofstream noteFile, dataFile;
00049 double freq;
00050 public:
00051 Calibration();
00052 ~Calibration();
00053 void setup();
00054 void centrifugeCalibration();
00055 void staticMagnetometerCalibration();
00056 void menu();
00057 };
00058
00059
00060 Calibration::Calibration() : sum_mb(3), sum_fb(3), sum_wb(3), sumSq_mb(3),
00061 sumSq_fb(3), sumSq_wb(3), avg_mb(3), avg_fb(3), avg_wb(3), max_mb(3),
00062 min_mb(3), bias_mb(3), scale_mb(3), std_mb(3), std_fb(3), std_wb(3),
00063 freqCutMb(3), freqCutFb(3), freqCutWb(3), imu()
00064 {
00065
00066 numCycles = 10000;
00067 device = "/dev/rfcomm0";
00068 file = "test";
00069 freq = 500;
00070 freqCutMb(0) = freqCutMb(1) = freqCutMb(2) = 1;
00071 freqCutFb(0) = freqCutFb(1) = 350;
00072 freqCutFb(2) = 150;
00073 freqCutWb(0) = freqCutWb(1) = freqCutWb(2) = 120;
00074 arm_length = 0.7;
00075 orientation = "+X";
00076 }
00077
00078
00079 Calibration::~Calibration()
00080 {
00081
00082 if (imu) delete imu;
00083
00084
00085 if (noteFile.is_open()) noteFile.close();
00086 if (dataFile.is_open()) dataFile.close();
00087 }
00088
00089
00090 void Calibration::menu()
00091 {
00092 while (1)
00093 {
00094 uvsim::clear();
00095 std::cout << "UVSIM IMU CALIBRATION APPLICATION" << std::endl;
00096 std::cout << "\nCurrent Settings " << std::endl;
00097 std::cout << "------------------------------------------------------------------" << std::endl;
00098 std::cout << "Number of Cycles: "<< numCycles << std::endl;
00099 std::cout << "Device: " << device << std::endl;
00100 std::cout << "Output File: " << file << std::endl;
00101 std::cout << "Output Frequency: " << freq << std::endl;
00102 std::cout << "Arm Length: " << arm_length << std::endl;
00103 std::cout << "Orientation: " << orientation << std::endl;
00104 std::cout << "Magnetometer Cutoff Frequencies: " << freqCutMb << std::endl;
00105 std::cout << "Accelerometer Cutoff Frequencies: " << freqCutFb << std::endl;
00106 std::cout << "Gyro Cutoff Frequencies: " << freqCutWb << std::endl;
00107 std::cout << "\nMenu" << std::endl;
00108 std::cout << "------------------------------------------------------------------" << std::endl;
00109 std::cout << "1) Change Settings" << std::endl;
00110 std::cout << "2) Run Centrifuge Calibration" << std::endl;
00111 std::cout << "3) Run Magnetometer Static Calibration" << std::endl;
00112 std::cout << "4) Quit" << std::endl;
00113 std::cout << "\nSelection: ";
00114 std::cin >> choice;
00115 std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
00116 switch (choice)
00117 {
00118 case 1:
00119 setup();
00120 break;
00121 case 2:
00122 centrifugeCalibration();
00123 break;
00124 case 3:
00125 staticMagnetometerCalibration();
00126 break;
00127 case 4:
00128 std::cout << "Exiting application." << std::endl;
00129 return;
00130 default:
00131 std::cout << "Unknown selection." << std::endl;
00132 break;
00133 }
00134 std::cout << "\nPress <enter> to continue ..." << std::endl;
00135 std::cin.get();
00136 }
00137 }
00138
00139
00140 void Calibration::setup ()
00141 {
00142
00143 std::cout << "Input Directions" << std::endl;
00144 std::cout << "------------------------------------------------------------------" << std::endl;
00145 std::cout << "For all vectors the following format is required: [3](x, y, z)" << std::endl;
00146 std::cout << "Press enter to accept default shown in {}" << std::endl;
00147
00148 std::cout << "\nSettings" << std::endl;
00149 std::cout << "------------------------------------------------------------------" << std::endl;
00150 std::cout << "How many readings to be averaged {" << numCycles << "} : ";
00151 if (std::cin.peek() != '\n') std::cin >> numCycles;
00152 else std::cin.get();
00153
00154 std::cout << "Device {" << device << "} : ";
00155 if (std::cin.peek() != '\n') std::cin >> device;
00156 else std::cin.get();
00157
00158 std::cout << "Output file {" << file << "} : ";
00159 if (std::cin.peek() != '\n') std::cin >> file;
00160 else std::cin.get();
00161
00162 std::cout << "Output Frequency Hz {" << freq << "} : ";
00163 if (std::cin.peek() != '\n') std::cin >> freq;
00164 else std::cin.get();
00165
00166 std::cout << "Arm Length {" << arm_length << "} : ";
00167 if (std::cin.peek() != '\n') std::cin >> arm_length;
00168 else std::cin.get();
00169
00170 std::cout << "Orientation {" << orientation << "} : ";
00171 if (std::cin.peek() != '\n') std::cin >> orientation;
00172 else std::cin.get();
00173
00174 std::cout << "Magnetometer Cutoff Frequency {" << freqCutMb << "} : ";
00175 if (std::cin.peek() != '\n') std::cin >> freqCutMb;
00176 else std::cin.get();
00177
00178 std::cout << "Accelerometer Cutoff Frequency {" << freqCutFb << "} : ";
00179 if (std::cin.peek() != '\n') std::cin >> freqCutFb;
00180 else std::cin.get();
00181
00182 std::cout << "Gyro Cutoff Frequency {" << freqCutWb << "} : ";
00183 if (std::cin.peek() != '\n') std::cin >> freqCutWb;
00184 else std::cin.get();
00185
00186
00187 }
00188
00189
00190 void Calibration::centrifugeCalibration()
00191 {
00192
00193 if (noteFile.is_open()) noteFile.close();
00194 noteFileName = file + ".notes";
00195 noteFile.open(noteFileName.c_str());
00196
00197
00198 if (dataFile.is_open()) dataFile.close();
00199 dataFileName = file + ".data";
00200 dataFile.open(dataFileName.c_str());
00201
00202
00203 std::cout << "\nCentrifuge Calibration Started" << std::endl;
00204 std::cout << "------------------------------------------------------------------" << std::endl;
00205 std::cout << "Please input frequency and voltage seperated with a space: ";
00206 getline(std::cin,notes);
00207
00208
00209 std::cout << "Waiting for imu to connect via device: " << device << std::endl;
00210 imu = new uvsim::Imu6DofSensor(device, freqCutMb, freqCutFb, freqCutWb);
00211
00212
00213 imu->start(freq);
00214
00215
00216 imu->update();
00217 max_mb = imu->mb;
00218 min_mb = imu->mb;
00219 sum_mb = sum_fb = sum_wb = sumSq_mb = sumSq_fb = sumSq_wb = zero_vector<double>(3);
00220
00221
00222 for (int cycle = 0; cycle<numCycles; cycle++)
00223 {
00224
00225 uvsim::clear();
00226 std::cout << 100.*(cycle+1)/numCycles << "% Complete" << std::endl;
00227
00228
00229 imu->update();
00230
00231
00232 for (int i=0;i<3;i++)
00233 {
00234
00235 if (imu->mb(i) > max_mb(i)) max_mb(i) = imu->mb(i);
00236 if (imu->mb(i) < min_mb(i)) min_mb(i) = imu->mb(i);
00237 }
00238
00239
00240 sum_mb=sum_mb+imu->mb;
00241 sum_fb=sum_fb+imu->fb;
00242 sum_wb=sum_wb+imu->wb;
00243
00244
00245 sumSq_mb=element_prod(imu->mb,imu->mb)+sumSq_mb;
00246 sumSq_fb=element_prod(imu->fb,imu->fb)+sumSq_fb;
00247 sumSq_wb=element_prod(imu->wb,imu->wb)+sumSq_wb;
00248 }
00249
00250
00251 imu->stop();
00252
00253
00254 avg_mb = sum_mb/numCycles;
00255 avg_fb = sum_fb/numCycles;
00256 avg_wb = sum_wb/numCycles;
00257
00258
00259 bias_mb = (max_mb + min_mb)/2;
00260
00261
00262 for (int i=0;i<3;i++)
00263 {
00264
00265 std_mb[i]=sqrt((sumSq_mb[i]/numCycles)-(avg_mb[i]*avg_mb[i]));
00266 std_fb[i]=sqrt((sumSq_fb[i]/numCycles)-(avg_fb[i]*avg_fb[i]));
00267 std_wb[i]=sqrt((sumSq_wb[i]/numCycles)-(avg_wb[i]*avg_wb[i]));
00268 }
00269
00270
00271 std::cout << "\nCentrifuge Calibration Results" << std::endl;
00272 std::cout << "------------------------------------------------------------------\n" << std::endl;
00273 std::cout << "Frequency & Voltage: " << notes << std::endl;
00274 std::cout << std::endl;
00275 std::cout << "Magnetometer" << std::endl;
00276 std::cout << "\tAverages: " << avg_mb << std::endl;
00277 std::cout << "\tStandard Deviations: " << std_mb << std::endl;
00278 std::cout << "\tMax: " << max_mb << std::endl;
00279 std::cout << "\tMin: " << min_mb << std::endl;
00280 std::cout << "\tBias: " << bias_mb << std::endl;
00281 std::cout << std::endl;
00282 std::cout << "Accelerometer" << std::endl;
00283 std::cout << "\tAverages: " << avg_fb << std::endl;
00284 std::cout << "\tStandard Deviations: " << std_fb << std::endl;
00285 std::cout << std::endl;
00286 std::cout << "Gyros" << std::endl;
00287 std::cout << "\tAverages: " << avg_wb << std::endl;
00288 std::cout << "\tStandard Deviations: " << std_wb << std::endl;
00289
00290
00291 noteFile << orientation << " " << arm_length << " " << numCycles << " " << notes << std::endl;
00292 dataFile << avg_mb << " " << avg_fb << " " << avg_wb << std::endl;
00293 }
00294
00295
00296 void Calibration::staticMagnetometerCalibration()
00297 {
00298
00299 if (dataFile.is_open()) dataFile.close();
00300 dataFileName = file + ".data";
00301 dataFile.open(dataFileName.c_str());
00302
00303
00304 std::cout << "\nStatic Magnetometer Calibration Started" << std::endl;
00305 std::cout << "------------------------------------------------------------------\n" << std::endl;
00306
00307
00308 std::cout << "Waiting for imu to connect via device: " << device << std::endl;
00309 imu = new uvsim::Imu6DofSensor(device, freqCutMb, freqCutFb, freqCutWb);
00310
00311
00312 imu->start(freq);
00313
00314
00315 imu->update();
00316 max_mb = imu->mb;
00317 min_mb = imu->mb;
00318 sum_mb = sum_fb = sum_wb = sumSq_mb = sumSq_fb = sumSq_wb = zero_vector<double>(3);
00319
00320
00321 for (int cycle = 0; cycle<numCycles; cycle++)
00322 {
00323
00324 uvsim::clear();
00325 std::cout << 100.*(cycle+1)/numCycles << "% Complete" << std::endl;
00326
00327
00328 imu->update();
00329
00330
00331 for (int i=0;i<3;i++)
00332 {
00333
00334 if (imu->mb(i) > max_mb(i)) max_mb(i) = imu->mb(i);
00335 if (imu->mb(i) < min_mb(i)) min_mb(i) = imu->mb(i);
00336 }
00337
00338
00339 sum_mb=sum_mb+imu->mb;
00340 sum_fb=sum_fb+imu->fb;
00341 sum_wb=sum_wb+imu->wb;
00342
00343
00344 sumSq_mb=element_prod(imu->mb,imu->mb)+sumSq_mb;
00345 sumSq_fb=element_prod(imu->fb,imu->fb)+sumSq_fb;
00346 sumSq_wb=element_prod(imu->wb,imu->wb)+sumSq_wb;
00347 }
00348
00349
00350 imu->stop();
00351
00352
00353 avg_mb = sum_mb/numCycles;
00354 avg_fb = sum_fb/numCycles;
00355 avg_wb = sum_wb/numCycles;
00356
00357
00358 for (int i=0; i< max_mb.size(); i++)
00359 {
00360 scale_mb(i) = 2/(max_mb(i)-min_mb(i));
00361 bias_mb(i) = 1-scale_mb(i)*max_mb(i);
00362 }
00363
00364
00365 for (int i=0;i<3;i++)
00366 {
00367
00368 std_mb[i]=sqrt((sumSq_mb[i]/numCycles)-(avg_mb[i]*avg_mb[i]));
00369 std_fb[i]=sqrt((sumSq_fb[i]/numCycles)-(avg_fb[i]*avg_fb[i]));
00370 std_wb[i]=sqrt((sumSq_wb[i]/numCycles)-(avg_wb[i]*avg_wb[i]));
00371 }
00372
00373
00374 std::cout << "\nStatic Magnetometer Results" << std::endl;
00375 std::cout << "------------------------------------------------------------------\n" << std::endl;
00376 std::cout << "Magnetometer" << std::endl;
00377 std::cout << "\tAverages: " << avg_mb << std::endl;
00378 std::cout << "\tStandard Deviations: " << std_mb << std::endl;
00379 std::cout << "\tMax: " << max_mb << std::endl;
00380 std::cout << "\tMin: " << min_mb << std::endl;
00381 std::cout << "\tBias: " << bias_mb << std::endl;
00382 std::cout << "\tScale: " << scale_mb << std::endl;
00383
00384
00385 for (int i=0; i<scale_mb.size(); i++)
00386 dataFile << scale_mb(i) << " " << -bias_mb(i) << std::endl;
00387 }
00388
00389
00390 int main()
00391 {
00392 Calibration calibration;
00393 calibration.menu();
00394 return 0;
00395 }
00396
00397