TestrigGUI.cpp

00001 /*
00002  * testrigGUI.cc
00003  *
00004  *  Created on: Feb 18, 2010
00005  *      Author: uscr
00006  */
00007 
00008 #include <opencv/cv.h>
00009 #include <opencv/highgui.h>
00010 
00011 #include <pthread.h>
00012 #include <cmath>
00013 #include <cstdio>
00014 
00015 #include <QtCore/QString>
00016 #include <QtGui/QPen>
00017 
00018 #include "TestrigGUI.h"
00019 
00020 extern struct CollectedData myData;
00021 extern struct KalmanFilterData pitchFilter, rollFilter;
00022 extern pthread_mutex_t camMutex, imuMutex;
00023 extern IplImage * frame;
00024 
00025 TestrigGUI::TestrigGUI() {
00026         ui.setupUi(this);
00027         connect (this, SIGNAL(readyToUpdateGUI()), this, SLOT(updateGUIDisplay()));
00028         connect (ui.controlVelocity, SIGNAL(valueChanged(int)), this, SLOT(updateControls()));
00029         connect (ui.controlYaw, SIGNAL(valueChanged(int)), this, SLOT(updateControls()));
00030         connect (ui.reset_pitch, SIGNAL(clicked()), this, SLOT(updatePitchFilter()));
00031         connect (ui.reset_roll, SIGNAL(clicked()), this, SLOT(updateRollFilter()));
00032 
00033         //curIplImage = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 3);
00034         frameCounter = -1;
00035         ui.roll_cmp->setTitle(QString("Roll Filtered Angle"));
00036         ui.pitch_cmp->setTitle(QString("Pitch Filtered Angle"));
00037         ui.roll_raw->setTitle(QwtText("Roll Raw Data (<font color=#006699>Gyro</font>, <font color=#999966>Accel</font>)"));
00038         ui.pitch_raw->setTitle(QwtText("Pitch Raw Data (<font color=#006699>Gyro</font>, <font color=#999966>Accel</font>)"));
00039 
00040         for (int i = 0; i < NUM_POINTS; i++) {
00041                 myGuiPlotData.camPitchAngle[i] = 0;
00042                 myGuiPlotData.camRollAngle[i] = 0;
00043                 myGuiPlotData.imuPitchAccelVal[i] = 0;
00044                 myGuiPlotData.imuPitchAngle[i] = 0;
00045                 myGuiPlotData.imuPitchGyroVal[i] = 0;
00046                 myGuiPlotData.imuRollAccelVal[i] = 0;
00047                 myGuiPlotData.imuRollAngle[i] = 0;
00048                 myGuiPlotData.imuRollGyroVal[i] = 0;
00049                 myGuiPlotData.imuDeltaT[i] = 0;
00050         }
00051         myGuiPlotData.imuLastT = 0;
00052 
00053         rollGyroCurve = new QwtPlotCurve();
00054         rollAccelCurve = new QwtPlotCurve();
00055         rollFilterCurve = new QwtPlotCurve();
00056         pitchGyroCurve = new QwtPlotCurve();
00057         pitchAccelCurve = new QwtPlotCurve();
00058         pitchFilterCurve = new QwtPlotCurve();
00059 
00060         rollGyroCurve->setRawData(incrementalTime, myGuiPlotData.imuRollGyroVal, NUM_POINTS);
00061         rollGyroCurve->setPen(QPen(QColor(0, 102, 153)));
00062         rollAccelCurve->setRawData(incrementalTime, myGuiPlotData.imuRollAccelVal, NUM_POINTS);
00063         rollAccelCurve->setPen(QPen(QColor(153, 153, 102)));
00064         rollFilterCurve->setRawData(incrementalTime, myGuiPlotData.imuRollAngle, NUM_POINTS);
00065         pitchGyroCurve->setRawData(incrementalTime, myGuiPlotData.imuPitchGyroVal, NUM_POINTS);
00066         pitchGyroCurve->setPen(QPen(QColor(0, 102, 153)));
00067         pitchAccelCurve->setRawData(incrementalTime, myGuiPlotData.imuPitchAccelVal, NUM_POINTS);
00068         pitchAccelCurve->setPen(QPen(QColor(153, 153, 102)));
00069         pitchFilterCurve->setRawData(incrementalTime, myGuiPlotData.imuPitchAngle, NUM_POINTS);
00070 
00071         ui.roll_raw->setAutoReplot(false);
00072         ui.roll_cmp->setAutoReplot(false);
00073         ui.pitch_raw->setAutoReplot(false);
00074         ui.pitch_cmp->setAutoReplot(false);
00075 
00076         rollGyroCurve->attach(ui.roll_raw);
00077         rollAccelCurve->attach(ui.roll_raw);
00078         rollFilterCurve->attach(ui.roll_cmp);
00079         pitchGyroCurve->attach(ui.pitch_raw);
00080         pitchAccelCurve->attach(ui.pitch_raw);
00081         pitchFilterCurve->attach(ui.pitch_cmp);
00082         //ui.roll_raw->setAxisScale(0, 200, 800, 100);
00083         ui.roll_raw->setAxisScale(2, 0, 10500, 2000);
00084         ui.roll_cmp->setAxisScale(2, 0, 10500, 2000);
00085         ui.pitch_raw->setAxisScale(2, 0, 10500, 2000);
00086         ui.pitch_cmp->setAxisScale(2, 0, 10500, 2000);
00087 
00088 
00089         fft_in = ( fftw_complex* ) fftw_malloc( sizeof( fftw_complex ) * NUM_POINTS );
00090         fft_out = ( fftw_complex* ) fftw_malloc( sizeof( fftw_complex ) * NUM_POINTS );
00091         plan_forward  = fftw_plan_dft_1d( NUM_POINTS, fft_in, fft_out, FFTW_FORWARD, FFTW_ESTIMATE );
00092 
00093         fftCurve = new QwtPlotCurve();
00094         fftCurve->setRawData(incrementalTime, myGuiPlotData.imuPitchAngle, NUM_POINTS);
00095         fftCurve->setStyle(QwtPlotCurve::Dots);
00096         ui.fft_plot->setAutoReplot(false);
00097         fftCurve->attach(ui.fft_plot);
00098         ui.fft_plot->setAxisScale(0, 0, 10000000, 1000000);
00099         ui.fft_plot->setAxisScale(2, 500, 1000, 100);
00100 
00101         ui.fft_select->insertItem(0, QString("Pitch Filtered Data"));
00102         ui.fft_select->insertItem(1, QString("Pitch Raw Gyro Data"));
00103         ui.fft_select->insertItem(2, QString("Pitch Raw Accel Data"));
00104         ui.fft_select->insertItem(3, QString("Roll Filtered Data"));
00105         ui.fft_select->insertItem(4, QString("Roll Raw Gyro Data"));
00106         ui.fft_select->insertItem(5, QString("Roll Raw Accel Data"));
00107 
00108 }
00109 
00110 TestrigGUI::~TestrigGUI() {
00111         rollGyroCurve->detach();
00112 
00113     fftw_destroy_plan( plan_forward );
00114     fftw_free( fft_in );
00115     fftw_free( fft_out );
00116 
00117         //cvReleaseImage (&curIplImage);
00118 }
00119 
00120 void TestrigGUI::emitReadyToUpdateGUI() {
00121         emit readyToUpdateGUI();
00122 }
00123 
00124 double TestrigGUI::getMean(double * data) {
00125         double mean = 0;
00126 
00127         for (int i = 0; i < NUM_POINTS; i++) {
00128                 mean += data[i];
00129         }
00130 
00131         return mean / (double) NUM_POINTS;
00132 }
00133 
00134 double TestrigGUI::getStandardDeviation(double * data) {
00135 
00136         int sdWidth = 30;
00137         double mean = 0, var = 0;
00138         int startVal = myGuiData.oldestPoint - sdWidth;
00139         if (startVal < 0)
00140                 startVal += NUM_POINTS;
00141 
00142         for (int i = startVal; i != myGuiData.oldestPoint; i++) {
00143                 mean += data[i];
00144                 if (i + 1 == NUM_POINTS)
00145                         i = -1;
00146         }
00147 
00148         mean /= (double) sdWidth;
00149 
00150         for (int i = startVal; i != myGuiData.oldestPoint; i++) {
00151                 var += (data[i] - mean)*(data[i] - mean);
00152                 if (i + 1 == NUM_POINTS)
00153                         i = -1;
00154         }
00155 
00156         var /= (double) sdWidth;
00157 
00158         return var;
00159 }
00160 
00161 
00162 void TestrigGUI::updateGUIDisplay() {
00163 
00164 
00165         //Calculate Statistics:
00166         pthread_mutex_lock(&camMutex);
00167         pthread_mutex_lock(&imuMutex);
00168         memcpy(&myGuiData, &myData, sizeof(struct CollectedData));
00169         memcpy(&guiRollFilter, &rollFilter, sizeof(struct KalmanFilterData));
00170         memcpy(&guiPitchFilter, &pitchFilter, sizeof(struct KalmanFilterData));
00171         pthread_mutex_unlock(&imuMutex);
00172         pthread_mutex_unlock(&camMutex);
00173 
00174         //Throw in the stat stuff at the bottom of the page
00175         ui.pitch_accel_sd->setText(QString::number(getStandardDeviation(myGuiData.imuPitchAccelVal), 'g', 3));
00176         ui.pitch_gyro_sd->setText(QString::number(getStandardDeviation(myGuiData.imuPitchGyroVal), 'g', 3));
00177         ui.roll_accel_sd->setText(QString::number(getStandardDeviation(myGuiData.imuRollAccelVal), 'g', 3));
00178         ui.roll_gyro_sd->setText(QString::number(getStandardDeviation(myGuiData.imuRollGyroVal), 'g', 3));
00179         ui.imu_up_per_sec->setText(QString::number( (1000.0 / getMean(myGuiData.imuDeltaT)) , 'g', 3));
00180         //camupdates
00181 
00182         //update kalman stuff if the button is unchecked
00183         if (!ui.pauseKalmanUpdates->isChecked()) {
00184 
00185                 ui.roll_accel_var->setValue(guiRollFilter.Sz*1000);
00186                 ui.roll_gyro_var->setValue(guiRollFilter.Sw_00);
00187                 ui.roll_bias_var->setValue(guiRollFilter.Sw_11);
00188 
00189                 ui.pitch_accel_var->setValue(guiPitchFilter.Sz*1000);
00190                 ui.pitch_gyro_var->setValue(guiPitchFilter.Sw_00);
00191                 ui.pitch_bias_var->setValue(guiPitchFilter.Sw_11);
00192         }
00193 
00194         ui.roll_kalman_0->setText(QString::number(guiRollFilter.K_0));
00195         ui.roll_kalman_1->setText(QString::number(guiRollFilter.K_1));
00196         ui.roll_p_00->setText(QString::number(guiRollFilter.P_00));
00197         ui.roll_p_01->setText(QString::number(guiRollFilter.P_01));
00198         ui.roll_p_10->setText(QString::number(guiRollFilter.P_10));
00199         ui.roll_p_11->setText(QString::number(guiRollFilter.P_11));
00200 
00201         ui.pitch_kalman_0->setText(QString::number(guiPitchFilter.K_0));
00202         ui.pitch_kalman_1->setText(QString::number(guiPitchFilter.K_1));
00203         ui.pitch_p_00->setText(QString::number(guiPitchFilter.P_00));
00204         ui.pitch_p_01->setText(QString::number(guiPitchFilter.P_01));
00205         ui.pitch_p_10->setText(QString::number(guiPitchFilter.P_10));
00206         ui.pitch_p_11->setText(QString::number(guiPitchFilter.P_11));
00207 
00208         int startVal = myGuiData.oldestPoint + 1;
00209         if (startVal < 0)
00210                 startVal += NUM_POINTS;
00211 
00212         switch (ui.tabWidget->currentIndex()) {
00213         //=========================================================================
00214         case 0: //graph stuffs
00215 
00216                 //rotate all of the relevant data arrays to the correct value so that we don't
00217                 // get the line from the last value to the first:
00218                 //also get the incremental time (AKA ranges from 0ms-last ms)
00219                 incrementalTime[0] = 0;
00220                 myGuiPlotData.imuPitchAccelVal[0] = myGuiData.imuPitchAccelVal[myGuiData.oldestPoint];
00221                 myGuiPlotData.imuPitchGyroVal[0] = myGuiData.imuPitchGyroVal[myGuiData.oldestPoint];
00222                 myGuiPlotData.imuPitchAngle[0] = myGuiData.imuPitchAngle[myGuiData.oldestPoint];
00223 
00224                 myGuiPlotData.imuRollAccelVal[0] = myGuiData.imuRollAccelVal[myGuiData.oldestPoint];
00225                 myGuiPlotData.imuRollGyroVal[0] = myGuiData.imuRollGyroVal[myGuiData.oldestPoint];
00226                 myGuiPlotData.imuRollAngle[0] = myGuiData.imuRollAngle[myGuiData.oldestPoint];
00227 
00228                 for (int j = 1, i = startVal; j < NUM_POINTS; i++, j++) {
00229 
00230                         myGuiPlotData.imuPitchAccelVal[j] = myGuiData.imuPitchAccelVal[i];
00231                         myGuiPlotData.imuPitchGyroVal[j] = myGuiData.imuPitchGyroVal[i];
00232                         myGuiPlotData.imuPitchAngle[j] = myGuiData.imuPitchAngle[i];
00233                         myGuiPlotData.imuRollAccelVal[j] = myGuiData.imuRollAccelVal[i];
00234                         myGuiPlotData.imuRollGyroVal[j] = myGuiData.imuRollGyroVal[i];
00235                         myGuiPlotData.imuRollAngle[j] = myGuiData.imuRollAngle[i];
00236 
00237                         incrementalTime[j] =  myGuiData.imuDeltaT[i] + incrementalTime[j - 1];
00238 
00239                         if (i + 1 == NUM_POINTS)
00240                                 i = -1;
00241                 }
00242 
00243                 if (ui.constPitchAxis->isChecked()) {
00244                         ui.pitch_cmp->setAxisScale(0, -30.0, 30.0, 5.0);
00245                 } else {
00246                         ui.pitch_cmp->setAxisAutoScale(0);
00247                 }
00248                 if (ui.constRollAxis->isChecked()) {
00249                         ui.roll_cmp->setAxisScale(0, -30.0, 30.0, 5.0);
00250                 } else {
00251                         ui.roll_cmp->setAxisAutoScale(0);
00252                 }
00253 
00254                 ui.roll_raw->replot();
00255                 ui.pitch_raw->replot();
00256                 ui.roll_cmp->replot();
00257                 ui.pitch_cmp->replot();
00258                 break;
00259         //=========================================================================
00260         case 1: //fft stuffs
00261 
00262                 double * fftDataArray;
00263 
00264                 switch (ui.fft_select->currentIndex()) {
00265                 case 0: //pitch filtered data
00266                         fftDataArray = myGuiData.imuPitchAngle;
00267                         break;
00268                 case 1: //pitch gyro data
00269                         fftDataArray = myGuiData.imuPitchGyroVal;
00270                         break;
00271                 case 2: //pitch accel data
00272                         fftDataArray = myGuiData.imuPitchAccelVal;
00273                         break;
00274                 case 3: //roll filtered data
00275                         fftDataArray = myGuiData.imuRollAngle;
00276                         break;
00277                 case 4: //roll gyro data
00278                         fftDataArray = myGuiData.imuRollGyroVal;
00279                         break;
00280                 case 5: //roll accel data
00281                         fftDataArray = myGuiData.imuRollAccelVal;
00282                         break;
00283                 default:
00284                         fftDataArray = myGuiData.imuPitchAngle;
00285                         break;
00286                 }
00287 
00288                 for (int j = 1, i = startVal; j < NUM_POINTS; i++, j++) {
00289                         fft_in[j][0] = fftDataArray[i];
00290                         fft_in[j][1] = 0;
00291 
00292                         if (i + 1 == NUM_POINTS)
00293                                 i = -1;
00294                 }
00295 
00296                 fftw_execute( plan_forward );
00297 
00298                 for (int i = 0; i < NUM_POINTS; i++) {
00299                         incrementalTime[i] = i;
00300                         myGuiPlotData.imuPitchAngle[i] = fft_out[i][0]*fft_out[i][0] + fft_out[i][1]*fft_out[i][1];
00301                 }
00302 
00303                 ui.fft_plot->replot();
00304                 break;
00305         //=========================================================================
00306         case 2: //control stuffs
00307 
00308 
00309                 break;
00310         //=========================================================================
00311         case 3: //cam stuffs
00312                 if (frameCounter != myData.frameCounter) {
00313 
00314                         pthread_mutex_lock(&camMutex);
00315                         frameCounter = myData.frameCounter;
00316                         //cvCvtColor(myData.currentCamImage, curIplImage, CV_BGR2RGB);
00317                         pthread_mutex_unlock(&camMutex);
00318 
00319                         //curQImage = QImage ((unsigned char *) curIplImage->imageData, curIplImage->width, curIplImage->height,
00320                         //              curIplImage->widthStep, QImage::Format_RGB888);
00321                         //ui.cameraLabel->setPixmap(QPixmap::fromImage(curQImage));
00322                 }
00323                 break;
00324         default:
00325                 break;
00326         }
00327 }
00328 
00329 
00330 
00331 
00332 void TestrigGUI::updateControls() {
00333 
00334 }
00335 
00336 void TestrigGUI::updatePitchFilter() {
00337         //if paused only do the following
00338         if (ui.pauseKalmanUpdates->isChecked()) {
00339 
00340                 pthread_mutex_lock(&imuMutex);
00341                 initializeKalmanFilter(&pitchFilter, ui.pitch_accel_var->value()/1000.0,
00342                                 ui.pitch_gyro_var->value(), ui.pitch_bias_var->value());
00343                 pthread_mutex_unlock(&imuMutex);
00344         }
00345 }
00346 
00347 void TestrigGUI::updateRollFilter() {
00348         //if paused only do the following
00349         if (ui.pauseKalmanUpdates->isChecked()) {
00350 
00351                 pthread_mutex_lock(&imuMutex);
00352                 initializeKalmanFilter(&rollFilter, ui.roll_accel_var->value()/1000.0,
00353                                 ui.roll_gyro_var->value(), ui.roll_bias_var->value());
00354                 pthread_mutex_unlock(&imuMutex);
00355         }
00356 }
Generated on Sun May 8 08:41:21 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3