00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "Ins.h"
00020 #include <iostream>
00021 #include <iomanip>
00022 #include <string>
00023 #include <time.h>
00024 #include <cmath>
00025
00026 using namespace boost::numeric::ublas;
00027
00028 namespace uvsim
00029 {
00030
00031
00032 Ins::Ins(std::string accelCalib, std::string gyroCalib, std::string magCalib,
00033 double frequency, Imu6DofSensor * imu):
00034 accelM(3), accelB(3), gyroM(3), gyroB(3), magM(3), magB(3),
00035 gyro(3), quatdot(4), quatdot0(4), accel(3), mag(3), quat0(4), accelInertial0(3),
00036 accelInertial(3), velocity(3), velocity0(3), specificForce(3),
00037 mag0(3), accel0(3), gyro0(3),
00038 quat(4), euler(3), W(4,4), DCM(3,3), freq(frequency), imu(imu)
00039 {
00040 std::cout << "Constructing Ins" << std::endl;
00041
00042
00043 std::ifstream accelFile, gyroFile, magFile;
00044
00045
00046 accelFile.open(accelCalib.c_str());
00047 gyroFile.open(gyroCalib.c_str());
00048 magFile.open(magCalib.c_str());
00049
00050
00051 accelFile >> accelM(0) >> accelB(0) >> accelM(1) >> accelB(1) >> accelM(2) >> accelB(2);
00052 gyroFile >> gyroM(0) >> gyroB(0) >> gyroM(1) >> gyroB(1) >> gyroM(2) >> gyroB(2);
00053 magFile >> magM(0) >> magB(0) >> magM(1) >> magB(1) >> magM(2) >> magB(2);
00054
00055
00056 accelFile.close();
00057 gyroFile.close();
00058 magFile.close();
00059
00060
00061 geoMag = new GeoMag(std::string(DATADIR)+="/data/WMM.COF",12);
00062
00063
00064 imu->start(freq);
00065
00066 std::cout << "Ins Constructed" << std::endl;
00067 }
00068
00069 void Ins::initializeStatic(double alt, double lat, double lon)
00070 {
00071 std::cout << "Performing Static Initialization" << std::endl;
00072
00073
00074 altitudeInit = alt;
00075 latitudeInit = lat*M_PI/180;
00076 longitudeInit = lon*M_PI/180;
00077
00078 altitude = altitudeInit;
00079 latitude = latitudeInit;
00080 longitude = longitudeInit;
00081
00082
00083 altitudedot = 0;
00084 latitudedot = 0;
00085 longitudedot = 0;
00086 quatdot = zero_vector<double>(4);
00087 accelInertial = zero_vector<double>(3);
00088 velocity = zero_vector<double>(3);
00089
00090
00091 sum_mag = sum_accel = sum_gyro = zero_vector<double>(3);
00092 sumSq_mag= sumSq_accel= sumSq_gyro = zero_vector<double>(3);
00093 avg_mag= avg_accel= avg_gyro = zero_vector<double>(3);
00094 std_mag= std_accel= std_gyro = zero_vector<double>(3);
00095
00096
00097 for (int j=0;j<initCycles;j++)
00098 {
00099
00100 read();
00101
00102
00103 sum_mag=sum_mag+mag;
00104 sum_accel=sum_accel+accel;
00105 sum_gyro=sum_gyro+gyro;
00106 sumSq_mag=element_prod(mag,mag)+sumSq_mag;
00107 sumSq_accel=element_prod(accel,accel)+sumSq_accel;
00108 sumSq_gyro=element_prod(gyro,gyro)+sumSq_gyro;
00109 }
00110
00111
00112 avg_mag = sum_mag*(1./initCycles);
00113 avg_accel = sum_accel*(1./initCycles);
00114 avg_gyro = sum_gyro*(1./initCycles);
00115
00116
00117 for (int i=0;i<3;i++)
00118 {
00119 std_mag(i)=sqrt((sumSq_mag(i)/initCycles)-(avg_mag(i)*avg_mag(i)));
00120 std_accel(i)=sqrt((sumSq_accel(i)/initCycles)-(avg_accel(i)*avg_accel(i)));
00121 std_gyro(i)=sqrt((sumSq_gyro(i)/initCycles)-(avg_gyro(i)*avg_gyro(i)));
00122 }
00123
00124
00125 std::cout << "average mag: " << avg_mag << std::endl;
00126 std::cout << "average accel: " << avg_accel << std::endl;
00127 std::cout << "average gyro: " << avg_gyro << std::endl;
00128
00129 std::cout << "stdDev mag: " << std_mag << std::endl;
00130 std::cout << "stdDev accel: " << std_accel << std::endl;
00131 std::cout << "stdDev gyro: " << std_gyro << std::endl;
00132
00133
00134 gyroB = gyroB - (180/M_PI)*avg_gyro;
00135
00136
00137 vector<double> axis0(3), axis1(3), quat0(4), quat1(4),
00138 magTempFrame(3), x(3), z(3);
00139 double angle0, angle1;
00140
00141
00142 z(0) = 0;
00143 z(1) = 0;
00144 z(2) = 1;
00145 x(0) = 1;
00146 x(1) = 0;
00147 x(2) = 0;
00148
00149
00150 axis0 = norm(crossProd(-avg_accel, z));
00151 angle0 = acos(inner_prod(-norm(avg_accel), z));
00152 quat0 = axisAngle2Quat(axis0, angle0);
00153 std::cout << "axis 0: " << axis0 << std::endl;
00154 std::cout << "angle 0 (deg): " << angle0*180/M_PI << std::endl;
00155 std::cout << "quat 0: " << quat0 << std::endl;
00156 std::cout << "eul 0: " << quat2Euler(quat0)*180/M_PI << std::endl;
00157
00158
00159 geoMag->update(altitude, 180/M_PI*latitude, 180/M_PI*longitude,magYear);
00160
00161 magTempFrame = quatRotate(quat0, avg_mag);
00162 magTempFrame(2) = 0;
00163 magTempFrame = norm(magTempFrame);
00164 axis1 = norm(crossProd(magTempFrame, x));
00165 std::cout << "magTempFrameProj: " << magTempFrame << std::endl;
00166 angle1 = acos(inner_prod(x, magTempFrame)) + M_PI/180*geoMag->dec;
00167 quat1 = axisAngle2Quat(axis1, angle1);
00168 std::cout << "axis 1: " << axis1 << std::endl;
00169 std::cout << "angle 1 (deg): " << angle1*180/M_PI << std::endl;
00170 std::cout << "quat 1: " << quat1 << std::endl;
00171 std::cout << "eul 1: " << quat2Euler(quat1)*180/M_PI << std::endl;
00172
00173
00174 quat = quatProd(quat1,quat0);
00175 quat = norm(quat);
00176 std::cout << "quat: " << quat << std::endl;
00177 std::cout << "roll, pitch, yaw (deg): " << quat2Euler(quat)*180/M_PI << std::endl;
00178
00179
00180 gettimeofday(&timeInitial , NULL);
00181 timePres = timeInitial;
00182
00183
00184 read();
00185
00186 std::cout << "Static Initialization Complete" << std::endl;
00187 }
00188
00189 void Ins::read()
00190 {
00191
00192 imu->update();
00193
00194
00195 mag = element_prod(magM, imu->mb) + magB;
00196 accel = (element_prod(accelM, imu->fb) + accelB)*g;
00197 gyro = (element_prod(gyroM, imu->wb) + gyroB)*M_PI/180;
00198
00199
00200 accel0 = accel;
00201 mag0 = mag;
00202 gyro0 = gyro;
00203
00204 quat0 = quat;
00205 quatdot0 = quatdot;
00206
00207 latitude0 = latitude;
00208 longitude0 = longitude;
00209 altitude0 = altitude;
00210
00211 latitudedot0 = latitudedot;
00212 longitudedot0 = longitudedot;
00213 altitudedot0 = altitudedot;
00214
00215 velocity0 = velocity;
00216 accelInertial0 = accelInertial;
00217 timePrev = timePres;
00218 }
00219
00220 void Ins::update()
00221 {
00222
00223 gettimeofday(&timePres , NULL);
00224
00225
00226 read();
00227
00228
00229
00230
00231
00232
00233 W(1,0) = W(2,3) = gyro(0);
00234 W(2,0) = W(3,1) = gyro(1);
00235 W(2,1) = W(0,3) = -gyro(2);
00236 W(3,0) = W(1,2) = gyro(2);
00237 W(3,2) = W(0,1) = -gyro(0);
00238 W(0,2) = W(1,3) = -gyro(1);
00239 W(0,0) = W(1,1) = W(2,2) = W(3,3) = 0;
00240
00241
00242 quatdot = 0.5*prod(W,quat0);
00243
00244
00245 quat = integrate(quatdot,quatdot0, quat0, freq);
00246
00247
00248 quat = norm(quat);
00249
00250
00251 euler = quat2Euler(quat);
00252
00253
00254 DCM(0,0) = pow(quat(0),2) + pow(quat(1),2) - pow(quat(2),2) - pow(quat(3),2);
00255 DCM(0,1) = 2 * (quat(1) * quat(2) - quat(0) * quat(3));
00256 DCM(0,2) = 2 * (quat(1) * quat(3) + quat(0) * quat(2));
00257 DCM(1,0) = 2 * (quat(1) * quat(2) + quat(0) * quat(3));
00258 DCM(1,1) = pow(quat(0),2) - pow(quat(1),2) + pow(quat(2),2) - pow(quat(3),2);
00259 DCM(1,2) = 2 * (quat(2) * quat(3) - quat(0) * quat(1));
00260 DCM(2,0) = 2 * (quat(1) * quat(3) - quat(0) * quat(2));
00261 DCM(2,1) = 2 * (quat(2) * quat(3) + quat(0) * quat(1));
00262 DCM(2,2) = pow(quat(0),2) - pow(quat(1),2) - pow(quat(2),2) + pow(quat(3),2);
00263
00264
00265 specificForce = prod(DCM, accel);
00266
00267
00268 latitudedot = velocity0(0) / (R0 + altitude0);
00269 longitudedot = velocity0(1) / (cos(latitude0) * (R0 + altitude0));
00270 altitudedot = -velocity0(2);
00271
00272
00273 latitude = integrate(latitudedot, latitudedot0, latitude0, freq);
00274 longitude = integrate(longitudedot, longitudedot0, longitude0, freq);
00275 altitude = integrate(altitudedot , altitudedot0, altitude0, freq);
00276
00277
00278 accelInertial(0) = specificForce(0) - velocity0(1) * (2*omega +
00279 longitudedot) * sin (latitude) + velocity0(2) * latitudedot;
00280 accelInertial(1) = specificForce(1) + velocity0(0) * (2 * omega
00281 + longitudedot) * sin (latitude) + velocity0(2) * (2 * omega +
00282 longitudedot) * cos (latitude);
00283 accelInertial(2) = specificForce(2) - velocity0(1) * (2 * omega +
00284 longitudedot) * cos (latitude) - velocity0(0) * latitudedot + g;
00285
00286
00287 velocity = integrate(accelInertial, accelInertial0, velocity0, freq);
00288
00289
00290 geoMag->update(altitude, 180/M_PI*latitude, 180/M_PI*longitude,magYear);
00291 }
00292
00293
00294 void Ins::print()
00295 {
00296
00297 std::cout << std::setprecision(5);
00298 std::cout << "\nTime Elapsed (s): " << elapsedTime(timeInitial, timePres) << std::endl;
00299 std::cout << "Frequency (Hz): " << freq << std::endl;
00300 std::cout << "Latitude (deg): " << latitude*180/M_PI << std::endl;
00301 std::cout << "Longitude (deg): " << longitude*180/M_PI << std::endl;
00302 std::cout << "Altitude (m): " << altitude << std::endl;
00303 std::cout << "Velocity (m/s): " << velocity << std::endl;
00304 std::cout << "Quat (): " << quat << std::endl;
00305 std::cout << "Euler (deg)- Roll: "<< euler(0)*180/M_PI <<" Pitch: " << euler(1)*180/M_PI <<" Yaw: " <<euler(2)*180/M_PI << std::endl;
00306 std::cout << "Accel (m/s^2): " << accel << std::endl;
00307 std::cout << "Accel Inertial (m/s^2): " << accelInertial << std::endl;
00308 std::cout << "Roll Rates (deg/s): " << gyro*180/M_PI << std::endl;
00309 std::cout << "Accel M and B: " << accelM << " " << accelB << std::endl;
00310 std::cout << "Gyro M and B: " << gyroM << " " << gyroB << std::endl;
00311
00312 std::cout << "Latitude Arclength (m): " << (R0 + altitude)*
00313 (latitude-latitudeInit) << std::endl;
00314 std::cout << "Longitude Arclength (m): " << (R0 + altitude)*
00315 (longitude-longitudeInit) << std::endl;
00316 std::cout << "Altitude Change (m): " << (altitude-altitudeInit) << std::endl;
00317 std::cout << "Distance Approx (m): " <<
00318 sqrt( pow((R0 + altitude)*(latitude-latitudeInit),2) +
00319 pow((R0 + altitude)*(longitude-longitudeInit),2) +
00320 pow(altitude - altitudeInit,2)) << std::endl;
00321 std::cout << "mag: " << mag << std::endl;
00322 std::cout << "mag heading in body frame: " << 180/M_PI*atan2(mag(1),mag(0)) << std::endl;
00323 std::cout << "mag inclination in body frame: " << 180/M_PI*atan2(mag(2), sqrt(mag(0)*mag(0)+mag(1)*mag(1))) << std::endl;
00324 std::cout << "dec: " << geoMag->dec << " dip: " << geoMag->dip << " ti: "
00325 << geoMag->ti << " gv: " << std::endl;
00326 imu->print();
00327 std::cout<<std::endl;
00328 }
00329
00330
00331
00332 void Ins::stop()
00333 {
00334 imu->stop();
00335 }
00336
00337
00338 Ins::~Ins()
00339 {
00340 stop();
00341 }
00342
00343
00344 }
00345
00346