2 * CarMainWindow main class
4 * @author Toni Jussila <toni.jussila@fudeco.com>
5 * @author Janne Änäkkälä <janne.anakkala@fudeco.com>
6 * @author Tiina Kivilinna-Korhola <tiina.kivilinna-korhola@fudeco.com>
7 * @author Olavi Pulkkinen <olavi.pulkkinen@fudeco.com>
8 * @author Rikhard Kuutti <rikhard.kuutti@fudeco.com>
9 * @author Kai Rasilainen <kai.rasilainen@fudeco.com>
10 * @author Jukka Kurttila <jukka.kurttila@fudeco.com>
11 * @copyright (c) 2010 Speed Freak team
12 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
15 #include "carmainwindow.h"
18 #define kAccelerometerSampleRate 40
19 #define kFilteringFactor 0.1
20 #define kSecondsInHour 3600
23 *Constructor of this class.
24 *@param QWidget pointer to parent object. By default the value is NULL.
26 CarMainWindow::CarMainWindow(QWidget *parent):QMainWindow(parent), ui(new Ui::CarMainWindow)
29 ui->tabWidget->setCurrentWidget(this->ui->StartTab);
31 //Disable start buttons before calibration
32 ui->autoStartButton->setEnabled(false);
33 ui->manualStartButton->setEnabled(false);
35 result = new ResultDialog();
36 //measure = new MeasureDialog();
37 welcomeDialog = new WelcomeDialog();
38 welcomeDialog->show();
40 initComboBoxStartTabUnits();
41 initListViewStartTabAccelerationCategories();
43 myLogin = new LoginWindow(this);
44 myCategorylist = new CategoryList();
45 myHttpClient = new HttpClient(this);
46 myRegistration = new Registration(this);
47 connect(myRegistration,SIGNAL(sendregistration()),this,SLOT(regUserToServer()));
48 connect(myLogin,SIGNAL(userNameChanged()),this,SLOT(userLogin()));
49 connect(myHttpClient->myXmlreader, SIGNAL(receivedCategoryList()), this, SLOT(setCategoryCompoBox()));
50 connect(myHttpClient->myXmlreader, SIGNAL(receivedTop10List()), this, SLOT(showTop10()));
51 myRoute = new RouteDialog( this);
54 location = new Maemo5Location(this);
55 gpsData = new GPSData(location);
56 connect(location,SIGNAL(agnss()),this,SLOT(gpsStatus()));
57 gpsTime = new QDateTime();
58 gpsTimer = new QTimer();
59 connect(gpsTimer, SIGNAL(timeout()),this, SLOT(gpsTimerTimeout()));
61 gpsSpeedPrevious = 0.0;
62 gpsAcceleration = 0.0;
63 timeFromGps = 0.0; //Measure-tab view.
68 counterForSaveResults = 0;
72 accelerometer = new Accelerometer();
73 movingAverageZ = new MovingAverage(10);
75 reverseAccelerationFlag = false;
76 vehicleStartedMoving = false;
80 accelerationStartThreshold = 0.1;
82 accelerometerTimer = new QTimer(this);
83 connect(accelerometerTimer, SIGNAL(timeout()), this, SLOT(readAccelerometerData()));
84 //accelerometerTimer->start(kAccelerometerSampleRate);
87 calculate = new Calculate();
88 connect(calculate, SIGNAL(checkPointReached()), this, SLOT(handleCheckPoint()));
90 resetAccelerometerMeasurements();
92 measures = new Measures();
93 measures->initializeMembers();
95 this->timer->setInterval(100);
97 connect(this->timer, SIGNAL(timeout()), this, SLOT(after_timeout()));
98 connect(myLogin, SIGNAL( userNameChanged()), this, SLOT(updateUserName()));
100 ui->labelMeasureTabResult->hide();
101 ui->pushButtonShowResultDialog->setEnabled(false);
102 ui->pushButtonShowResultDialog->setEnabled(false);
104 this->setWindowTitle("Speed Freak");
108 *Destructor of this class. Deletes all dynamic objects and sets them to NULL.
110 CarMainWindow::~CarMainWindow()
116 delete myCategorylist;
117 myCategorylist = NULL;
118 delete welcomeDialog;
119 welcomeDialog = NULL;
129 gpsSpeedPrevious = 0.0;
130 gpsAcceleration = 0.0;
137 *This function is used to .
140 void CarMainWindow::changeEvent(QEvent *e)
142 QMainWindow::changeEvent(e);
144 case QEvent::LanguageChange:
145 ui->retranslateUi(this);
153 *This slot function is called when ever list view is update. Start-tab view.
155 void CarMainWindow::on_listViewStartTabAccelerationCategories_clicked(QModelIndex index)
157 QString str = index.data().toString();
158 QStringList list = str.split("-");
159 QStringList list2 = list[1].split(" ");
161 ui->lineEditStartTabMin->setText(list[0]);
162 ui->lineEditStartTabMax->setText(list2[0]);
163 updateComboBoxStartTabUnits(list2[1]);
167 *This slot function is called when ever auto start button clicked. Start-tab view.
168 *@todo Check setDiagramGapStem(100) <- (choiceInt == 2)
170 void CarMainWindow::on_autoStartButton_clicked()
172 measures->initializeMembers();
173 resetAccelerometerMeasurements();
174 ui->pushButtonSendResult->setEnabled(false);
175 ui->pushButtonShowResultDialog->setEnabled(false);
176 choice = ui->listViewStartTabAccelerationCategories->currentIndex();
177 choiceInt = choice.row();
178 //qDebug() << "choiceInt" << choiceInt << " " << catList.at(choiceInt);
181 ui->labelMeasureTabHeader->setText("Accelerate to 40 km/h");
182 result->setDiagramGapStem(75);
184 else if (choiceInt == 1)
186 ui->labelMeasureTabHeader->setText("Accelerate to 100 km/h");
187 result->setDiagramGapStem(30);
189 else if (choiceInt == 2)
191 ui->labelMeasureTabHeader->setText("Accelerate to 10 km/h");
192 result->setDiagramGapStem(100);
196 ui->labelMeasureTabHeader->setText("Accelerate to 80 km/h");
197 result->setDiagramGapStem(37.5);
199 ui->labelMeasureTabResult->setText("");
201 this->accelerometerTimer->start(kAccelerometerSampleRate);
202 this->timer->start();
205 ui->tabWidget->setCurrentWidget(this->ui->tabMeasureResult);
209 *This slot function is called when ever list view is update. Start-tab view.
210 *@param QString unit.
212 void CarMainWindow::updateComboBoxStartTabUnits(QString unit)
214 ui->comboBoxStartTabUnits->setCurrentIndex(ui->comboBoxStartTabUnits->findText(unit, Qt::MatchExactly));
218 *This function is used to init unit combobox. Start-tab view.
220 void CarMainWindow::initComboBoxStartTabUnits()
222 units << "km/h" << "km" << "h" << "m" << "min" << "Mile" << "Mph" << "in" << "ft" << "yrd";
223 ui->comboBoxStartTabUnits->addItems(units);
227 *This function is used to set items to unit combobox. Start-tab view.
228 *@param QStringlist units
230 void CarMainWindow::setComboBoxStartTabUnits(QStringList units)
232 ui->comboBoxStartTabUnits->addItems(units);
236 *This function is used to init listViewStartTabAccelerationCategories. Start-tab view.
237 *@todo During development categories index values that are used for measuring are hardcoded
238 *@todo and accelerationCategoriesStartTab and catList are used instead of using
239 *@todo CategoryList::categoryList and CategoryList::cats.
241 void CarMainWindow::initListViewStartTabAccelerationCategories()
243 //Connect the user`s choice fron GUI to a correct variable name
244 catList.insert(0,"acceleration-0-40");
245 catList.insert(1,"acceleration-0-100");
246 catList.insert(2,"acceleration-0-10");
248 accelerationCategoriesStartTab << "0-40 km/h" << "0-100 km/h" << "0-10 km/h";
249 //<< "0-1/4 Mile" << "0-1/8 Mile" << "50-100 Mile" << "0-60 Mph" << "0-100 m" << "0-50 ft" << "0-50 yrd" << "0-500 in";
250 QAbstractItemModel *model = new StringListModel(accelerationCategoriesStartTab);
251 ui->listViewStartTabAccelerationCategories->setModel(model);
255 *This function is used to set items to listViewStartTabAccelerationCategories. Start-tab view.
256 *@param QStringlist accelerationCategoriesStartTab
258 void CarMainWindow::setListViewStartTabAccelerationCategories(QStringList accelerationCategoriesStartTab)
260 QAbstractItemModel *model = new StringListModel(accelerationCategoriesStartTab);
261 ui->listViewStartTabAccelerationCategories->setModel(model);
264 void CarMainWindow::setLabelInfoToUser(QString infoText)
266 ui->labelInfoToUser->setText(infoText);
270 *This function is used to set items to category combobox. Top-tab view.
273 void CarMainWindow::setCategoryCompoBox()
275 qDebug() << "_setCategoryCompoBox";
276 ui->comboBoxTopCategory->addItems(myHttpClient->myXmlreader->myCategoryList->getCategoryList());
280 *This function prcesses UI updating after a new top10List has been received.
281 *@todo Check where limitNr is taken, fixed or user input, see on_comboBoxTopCategory_currentIndexChanged.
283 void CarMainWindow::showTop10()
286 setListViewTopList(recentCategory, limitNr);
290 *This function is used to set items to labelTopList. Top-tab view.
292 *@param Size, number of results.
294 void CarMainWindow::setListViewTopList(QString category, int size)
296 qDebug() << "_setListViewTopList";
298 topList.append(myHttpClient->myXmlreader->myCategoryList->getTopList(category, size));
299 ui->labelTopList->setText(topList);
303 *This slot function is called when speed is achieved in measure dialog. Opens result dialog.
305 void CarMainWindow::openResultView()
311 *This slot function is called when registrate button is clicked.
313 void CarMainWindow::on_registratePushButton_clicked()
315 myRegistration->show();
319 *This slot function is called when ever refresh button clicked. Top-tab view.
321 void CarMainWindow::on_buttonTopRefresh_clicked()
323 myHttpClient->requestCategories();
327 *This slot function is called when ever category combobox current index changed. Top-tab view.
328 *@param QString category.
329 *@todo Check where limitNr is taken, fixed or user input, see showTop10.
331 void CarMainWindow::on_comboBoxTopCategory_currentIndexChanged(QString category)
333 qDebug() << "_on_comboBoxTopCategory_currentIndexChanged: " << category;
334 recentCategory = category; //for showTop10()
336 QString limit = QString::number(limitNr);
337 myHttpClient->requestTopList(category, limit);
341 *This slot function is called when set/change user button is clicked.
343 void CarMainWindow::on_setUserPushButton_clicked()
349 *@brief Just for development, for the real button is not shown until
350 *measurin started and there are results.
351 *@todo Implement with real code and yet leave sendXml in the bottom in use.
353 void CarMainWindow::on_manualStartButton_clicked()
359 * This slot function is called when timer gives timeout signal. Checks current speed
360 * and stores times in measure class.
362 void CarMainWindow::after_timeout()
364 //IF GPS checkbox is ON
365 if (ui->gpsOnCheckBox->isChecked())
367 if ( gpsSpeed > 1.0 )
375 ui->labelMeasureTabSpeed->setText(QString::number(this->speed)); //Set speed. //Measure-tab view.
376 ui->labelMeasureTabTime->setText(QString::number(this->time)); //Set time. //Measure-tab view.
381 * This slot function is called when Abort button is clicked.
383 void CarMainWindow::on_pushButtonMeasureTabAbort_clicked()
385 ui->pushButtonSendResult->setEnabled(false);
386 ui->pushButtonShowResultDialog->setEnabled(false);
387 ui->labelMeasureTabResult->hide();
388 ui->labelMeasureTabTime->setText("");
389 ui->labelMeasureTabSpeed->setText("");
390 measures->initializeMembers();
391 this->accelerometerTimer->stop();
395 ui->tabWidget->setCurrentWidget(this->ui->StartTab);
404 *This slot function is called when pushButtonSendResult is clicked.
405 *@todo Use real category value.
407 void CarMainWindow::on_pushButtonSendResult_clicked()
409 //Pick up relevant category name and pass it to the server
410 myHttpClient->sendResultXml(catList.at(choiceInt));
411 ui->pushButtonSendResult->setEnabled(false);
414 void CarMainWindow::updateUserName()
418 newUserName = myLogin->getUserName();
419 ui->userNameLabel->setText( "User: " + newUserName);
421 if (newUserName.length())
423 ui->setUserPushButton->setText( "Change User");
424 this->setWindowTitle("Speed Freak - " + newUserName);
428 ui->setUserPushButton->setText( "Set User");
429 this->setWindowTitle("Speed Freak");
433 void CarMainWindow::regUserToServer()
435 myHttpClient->requestRegistration();
439 void CarMainWindow::on_drawRoutePushButton_clicked()
441 QString routeFile = QString("route.txt");
442 if (myRoute->readRouteFromFile( routeFile) == true)
449 * Opens result dialog when show result button is clicked.
450 * Sends measures as parameter to the resultdialogs saveMeasuresToArray-function.
452 void CarMainWindow::on_pushButtonShowResultDialog_clicked()
454 result->saveMeasuresToArray(measures);
455 this->result->show();
458 void CarMainWindow::userLogin()
460 myHttpClient->checkLogin();
464 * Resets Accelerometer measurement variables
466 void CarMainWindow::resetAccelerometerMeasurements()
468 currentAcceleration = 0;
469 currentAccelerationString = "";
472 distanceTraveled = "";
473 //firstAcceleration = 0;
476 //lastScreenUpdateInSeconds = 0;
478 reverseAccelerationFlag = false;
480 //accelerometer->stop();
482 vehicleStartedMoving = false;
487 * This function is called to handle checkpoints
488 *@param totalTime total time elapsed since starting measurements
489 *@param currentSpeed current speed of the device
491 void CarMainWindow::handleCheckPoint(double totalTime, double currentSpeed)
493 switch (counterForSaveResults)
496 measures->setTime10kmh(totalTime);
500 measures->setTime20kmh(totalTime);
504 measures->setTime30kmh(totalTime);
508 measures->setTime40kmh(totalTime);
512 measures->setTime50kmh(totalTime);
516 measures->setTime60kmh(totalTime);
520 measures->setTime70kmh(totalTime);
524 measures->setTime80kmh(totalTime);
528 measures->setTime90kmh(totalTime);
532 measures->setTime100kmh(totalTime);
538 counterForSaveResults++;
540 if (choiceInt == 0 && measures->getTime40kmh() != 0)
542 setTimeAxisGapAndShowResult(measures->getTime40kmh());
544 this->accelerometerTimer->stop();
547 counterForSaveResults = 0;
549 else if (choiceInt == 1 && measures->getTime100kmh() != 0)
551 setTimeAxisGapAndShowResult(measures->getTime100kmh());
553 this->accelerometerTimer->stop();
556 counterForSaveResults = 0;
558 else if (choiceInt == 2 && measures->getTime10kmh() != 0)
560 setTimeAxisGapAndShowResult(measures->getTime10kmh());
562 this->accelerometerTimer->stop();
565 counterForSaveResults = 0;
567 else if (choiceInt != 1 && choiceInt != 0 && measures->getTime80kmh() != 0)
569 setTimeAxisGapAndShowResult(measures->getTime80kmh());
571 this->accelerometerTimer->stop();
574 counterForSaveResults = 0;
578 qDebug() << "something wrong in handleCheckPoint()";
583 *This function is called to read (and process) data from the accelerometer
585 void CarMainWindow::readAccelerometerData()
588 double changeInAcceleration = 0;
591 accelerometer->getAcceleration(x, y, z);
593 // keep the following line as close to the SetKinematicsProperties method as possible
594 currentTime = stopWatch.elapsed();
596 //accelerometer->smoothData(x, y, z);
599 movingAverageZ->Enqueue(z);
600 z = movingAverageZ->Average();
603 x -= accelerometer->getCalibrationX();
604 y -= accelerometer->getCalibrationY();
605 z -= accelerometer->getCalibrationZ();
607 QString str = QString("acc x: " + QString::number(x) + "\n" +
608 "acc y: " + QString::number(y) + "\n" +
609 "acc z: " + QString::number(z) + "\n");
611 currentAcceleration = z;//sqrt(x*x + y*y + z*z);
612 changeInAcceleration = currentAcceleration;
614 if (((fabs(changeInAcceleration) <= accelerationStartThreshold)
615 && !vehicleStartedMoving))
619 else if(!vehicleStartedMoving)
621 vehicleStartedMoving = true;
627 calculate->calculateParameters(changeInAcceleration, (currentTime - previousTime)/1000);
628 previousTime = currentTime;
630 s.sprintf("%.2f", changeInAcceleration);
631 currentAccelerationString = s;
634 speed = calculate->getCurrentSpeed();
635 speed = speed*3.6;//((speed*1000)/kSecondsInHour);
636 s.sprintf("%.1f", speed);
639 s.sprintf("%.2f", calculate->getDistanceTraveled());
640 distanceTraveled = s;
646 time = calculate->getTotalTime();
648 s.sprintf("%.2f", time);
651 str.append("ca: " + currentAccelerationString + " G\n" );
652 str.append("cspeed: " + currentSpeed + " km/h \n" );
653 str.append("dist: " + distanceTraveled + " m \n" );
654 str.append("time: " + totalTime + " s \n" );
656 if ((stopTime > 0) && (previousTime >= stopTime))
658 // we want to end at a stopping point that the user chose
660 resetAccelerometerMeasurements();
665 *This function is used to calibrate accelerometer
667 void CarMainWindow::calibrateAccelerometer()
669 resetAccelerometerMeasurements();
670 accelerometer->calibrate();
674 *This slot function is called when GPS on checkbox state changed. Route-tab view.
677 void CarMainWindow::on_gpsOnCheckBox_stateChanged(int GPSState)
679 //Stop polling GPS. Route-tab view.
682 ui->labelRouteTabGPSStatus->setText("GPS status: GPS off");
683 location->stopPollingGPS();
687 //Start polling GPS. Route-tab view.
690 ui->labelRouteTabGPSStatus->setText("GPS status: GPS on");
691 location->startPollingGPS();
696 *This slot function is called when GPS status changed. Route- and measure-tab view.
698 void CarMainWindow::gpsStatus()
700 //IF GPS checkbox is ON
701 if (ui->gpsOnCheckBox->isChecked())
703 //If GPS find 4 satellite.
704 if (location->getSatellitesInUse() >= 4)
706 //Set gps status. Route-tab view.
707 ui->labelRouteTabGPSStatus->setText("GPS ready");
709 //Set time. Route-tab view.
710 gpsTime->setTime_t(location->getTime());
711 QString gpsDateNow = gpsTime->toString("dd.MM.yyyy hh:mm:ss");
712 ui->labelRouteTabGPSTime->setText("GPS time: " + gpsDateNow);
714 //Set latitude & longitude. Route-tab view.
715 ui->labelRouteTabLatitude->setText("Latitude: " + QString::number(location->getLatitude()));
716 ui->labelRouteTabLongitude->setText("Longitude: " + QString::number(location->getLongitude()));
718 //Set rec status. Route-tab view.
719 if (ui->startRecPushButton->text() == "Stop recording")
721 ui->labelRouteTabRecStatus->setText("Recorded " + QString::number(gpsData->roundCounter) + " point");
724 //Get speed. Route- and Measure-tab view.
725 gpsSpeed = location->getSpeed();
727 //Set speed. Route-tab view.
728 ui->labelRouteTabSpeed->setText("Speed:" + QString::number(gpsSpeed) + "km/h +/-" + QString::number(location->getEps()) + "km/h");
733 ui->labelMeasureTabSpeed->setText(QString::number(gpsSpeed)); //Set speed. //Measure-tab view.
734 ui->labelMeasureTabTime->setText(QString::number(timeFromGps)); //Set time. //Measure-tab view.
739 timer->stop(); //Measure timer
740 ui->labelMeasureTabResult->setText(QString::number(timeFromGps));
741 ui->labelMeasureTabResult->show();
742 ui->pushButtonShowResultDialog->setEnabled(true);
743 ui->pushButtonShowResultDialog->setEnabled(true);
747 //If GPS find less than 4 satellite.
750 ui->labelRouteTabGPSStatus->setText("GPS status: Waiting for GPS");
760 *This slot function is called when gps timer timeout(10ms).
762 void CarMainWindow::gpsTimerTimeout()
767 //IF time is 1 second
768 if (time1000ms == 1000)
770 //Calculate acceleration 1/s
771 gpsSpeedPrevious = gpsSpeedNow; //Previous speed
772 gpsSpeedNow = (location->getSpeed())/3.6; //Speed now (m/s)
773 gpsAcceleration = (gpsSpeedNow - gpsSpeedPrevious)/1; //Calculate acceleration: speed now - previous speed / 1s.
774 //Set acceleration. Route-tab view.
775 ui->labelRouteTabAcceleration->setText("Acceleration: " + QString::number( gpsAcceleration ) + " m/s2");
779 //Set GPS update time. Route-tab view.
780 ui->labelRouteTabGPSUpdateTime->setText("GPS update time: " + QString::number(gpsUpdateTime) + " ms");
784 *This slot function is called when start rec push button clicked. Route-tab view.
786 void CarMainWindow::on_startRecPushButton_clicked()
788 //Start route recording.
789 if (ui->startRecPushButton->text() == "Start recording")
791 ui->startRecPushButton->setText("Stop recording");
792 ui->labelRouteTabRecStatus->setText("Recording started");
793 gpsData->startRouteRecording(ui->labelRouteTabGPSTime->text());
796 //Stop route recording.
797 else if (ui->startRecPushButton->text() == "Stop recording")
799 ui->startRecPushButton->setText("Start recording");
800 ui->labelRouteTabRecStatus->setText("Recording stopped");
801 gpsData->stopRouteRecording(ui->labelRouteTabGPSTime->text());
806 *Sets time axis right way in result dialog and shows target speed result.
807 *@param double pTime is the target speed result time which is shown to the user.
809 void CarMainWindow::setTimeAxisGapAndShowResult(double pTime)
811 ui->pushButtonShowResultDialog->setEnabled(true);
812 ui->pushButtonSendResult->setEnabled(true);
814 timeInteger.setNum(pTime);
815 ui->labelMeasureTabResult->show();
816 ui->labelMeasureTabResult->setText(timeInteger);
818 if (floor(pTime) <= 5)
820 result->setDiagramGapHorizontal(80);
823 else if (floor(pTime) <= 10)
825 result->setDiagramGapHorizontal(40);
830 result->setDiagramGapHorizontal(20);
834 void CarMainWindow::on_calibrateButton_clicked()
836 ui->autoStartButton->setEnabled(true);
837 ui->manualStartButton->setEnabled(true);
839 this->accelerometer->calibrate();