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 list3 = list[1].split(" ");
160 QStringList list2 = list[0].split(" ");
162 ui->lineEditStartTabMin->setText(list2[1]);
163 ui->lineEditStartTabMax->setText(list3[0]);
164 updateComboBoxStartTabUnits(list3[1]);
168 *This slot function is called when ever auto start button clicked. Start-tab view.
169 *@todo Check setDiagramGapStem(100) <- (choiceInt == 2)
171 void CarMainWindow::on_autoStartButton_clicked()
173 measures->initializeMembers();
174 resetAccelerometerMeasurements();
175 ui->pushButtonSendResult->setEnabled(false);
176 ui->pushButtonShowResultDialog->setEnabled(false);
177 choice = ui->listViewStartTabAccelerationCategories->currentIndex();
178 choiceInt = choice.row();
179 //qDebug() << "choiceInt" << choiceInt << " " << catList.at(choiceInt);
182 ui->labelMeasureTabHeader->setText("Accelerate to 40 km/h");
183 result->setDiagramGapStem(75);
185 else if (choiceInt == 1)
187 ui->labelMeasureTabHeader->setText("Accelerate to 100 km/h");
188 result->setDiagramGapStem(30);
190 else if (choiceInt == 2)
192 ui->labelMeasureTabHeader->setText("Accelerate to 10 km/h");
193 result->setDiagramGapStem(100);
197 ui->labelMeasureTabHeader->setText("Accelerate to 80 km/h");
198 result->setDiagramGapStem(37.5);
200 ui->labelMeasureTabResult->setText("");
202 this->accelerometerTimer->start(kAccelerometerSampleRate);
203 this->timer->start();
206 ui->tabWidget->setCurrentWidget(this->ui->tabMeasureResult);
210 *This slot function is called when ever list view is update. Start-tab view.
211 *@param QString unit.
213 void CarMainWindow::updateComboBoxStartTabUnits(QString unit)
215 ui->comboBoxStartTabUnits->setCurrentIndex(ui->comboBoxStartTabUnits->findText(unit, Qt::MatchExactly));
219 *This function is used to init unit combobox. Start-tab view.
221 void CarMainWindow::initComboBoxStartTabUnits()
223 units << "km/h" << "km" << "h" << "m" << "min" << "Mile" << "Mph" << "in" << "ft" << "yrd";
224 ui->comboBoxStartTabUnits->addItems(units);
228 *This function is used to set items to unit combobox. Start-tab view.
229 *@param QStringlist units
231 void CarMainWindow::setComboBoxStartTabUnits(QStringList units)
233 ui->comboBoxStartTabUnits->addItems(units);
237 *This function is used to init listViewStartTabAccelerationCategories. Start-tab view.
238 *@todo During development categories index values that are used for measuring are hardcoded
239 *@todo and accelerationCategoriesStartTab and catList are used instead of using
240 *@todo CategoryList::categoryList and CategoryList::cats.
242 void CarMainWindow::initListViewStartTabAccelerationCategories()
244 //Connect the user`s choice fron GUI to a correct variable name
245 catList.insert(0,"acceleration-0-40");
246 catList.insert(1,"acceleration-0-100");
247 catList.insert(2,"acceleration-0-10");
249 accelerationCategoriesStartTab << "Acceleration 0-40 km/h" << "Acceleration 0-100 km/h" << "Acceleration 0-10 km/h";
250 //<< "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";
251 QAbstractItemModel *model = new StringListModel(accelerationCategoriesStartTab);
252 ui->listViewStartTabAccelerationCategories->setModel(model);
256 *This function is used to set items to listViewStartTabAccelerationCategories. Start-tab view.
257 *@param QStringlist accelerationCategoriesStartTab
259 void CarMainWindow::setListViewStartTabAccelerationCategories(QStringList accelerationCategoriesStartTab)
261 QAbstractItemModel *model = new StringListModel(accelerationCategoriesStartTab);
262 ui->listViewStartTabAccelerationCategories->setModel(model);
265 void CarMainWindow::setLabelInfoToUser(QString infoText)
267 ui->labelInfoToUser->setText(infoText);
271 *This function is used to set items to category combobox. Top-tab view.
274 void CarMainWindow::setCategoryCompoBox()
276 qDebug() << "_setCategoryCompoBox";
277 ui->comboBoxTopCategory->addItems(myHttpClient->myXmlreader->myCategoryList->getCategoryList());
281 *This function prcesses UI updating after a new top10List has been received.
282 *@todo Check where limitNr is taken, fixed or user input, see on_comboBoxTopCategory_currentIndexChanged.
284 void CarMainWindow::showTop10()
287 setListViewTopList(recentCategory, limitNr);
291 *This function is used to set items to labelTopList. Top-tab view.
293 *@param Size, number of results.
295 void CarMainWindow::setListViewTopList(QString category, int size)
297 qDebug() << "_setListViewTopList";
299 topList.append(myHttpClient->myXmlreader->myCategoryList->getTopList(category, size));
300 ui->labelTopList->setText(topList);
304 *This slot function is called when speed is achieved in measure dialog. Opens result dialog.
306 void CarMainWindow::openResultView()
312 *This slot function is called when registrate button is clicked.
314 void CarMainWindow::on_registratePushButton_clicked()
316 myRegistration->show();
320 *This slot function is called when ever refresh button clicked. Top-tab view.
322 void CarMainWindow::on_buttonTopRefresh_clicked()
324 myHttpClient->requestCategories();
328 *This slot function is called when ever category combobox current index changed. Top-tab view.
329 *@param QString category.
330 *@todo Check where limitNr is taken, fixed or user input, see showTop10.
332 void CarMainWindow::on_comboBoxTopCategory_currentIndexChanged(QString category)
334 qDebug() << "_on_comboBoxTopCategory_currentIndexChanged: " << category;
335 recentCategory = category; //for showTop10()
337 QString limit = QString::number(limitNr);
338 myHttpClient->requestTopList(category, limit);
342 *This slot function is called when set/change user button is clicked.
344 void CarMainWindow::on_setUserPushButton_clicked()
350 *@brief Just for development, for the real button is not shown until
351 *measurin started and there are results.
352 *@todo Implement with real code and yet leave sendXml in the bottom in use.
354 void CarMainWindow::on_manualStartButton_clicked()
360 * This slot function is called when timer gives timeout signal. Checks current speed
361 * and stores times in measure class.
363 void CarMainWindow::after_timeout()
365 //IF GPS checkbox is ON
366 if (ui->gpsOnCheckBox->isChecked())
368 if ( gpsSpeed > 1.0 )
376 ui->labelMeasureTabSpeed->setText(QString::number(this->speed)); //Set speed. //Measure-tab view.
377 ui->labelMeasureTabTime->setText(QString::number(this->time)); //Set time. //Measure-tab view.
382 * This slot function is called when Abort button is clicked.
384 void CarMainWindow::on_pushButtonMeasureTabAbort_clicked()
386 ui->pushButtonSendResult->setEnabled(false);
387 ui->pushButtonShowResultDialog->setEnabled(false);
388 ui->labelMeasureTabResult->hide();
389 ui->labelMeasureTabTime->setText("");
390 ui->labelMeasureTabSpeed->setText("");
391 measures->initializeMembers();
392 this->accelerometerTimer->stop();
396 ui->tabWidget->setCurrentWidget(this->ui->StartTab);
405 *This slot function is called when pushButtonSendResult is clicked.
406 *@todo Use real category value.
408 void CarMainWindow::on_pushButtonSendResult_clicked()
410 //Pick up relevant category name and pass it to the server
411 myHttpClient->sendResultXml(catList.at(choiceInt));
412 ui->pushButtonSendResult->setEnabled(false);
415 void CarMainWindow::updateUserName()
419 newUserName = myLogin->getUserName();
420 ui->userNameLabel->setText( "User: " + newUserName);
422 if (newUserName.length())
424 ui->setUserPushButton->setText( "Change User");
425 this->setWindowTitle("Speed Freak - " + newUserName);
429 ui->setUserPushButton->setText( "Set User");
430 this->setWindowTitle("Speed Freak");
434 void CarMainWindow::regUserToServer()
436 myHttpClient->requestRegistration();
440 void CarMainWindow::on_drawRoutePushButton_clicked()
442 QString routeFile = QString("route.txt");
443 if (myRoute->readRouteFromFile( routeFile) == true)
449 void CarMainWindow::on_sendRoutePushButton_clicked()
451 myHttpClient->sendRouteXml();
455 * Opens result dialog when show result button is clicked.
456 * Sends measures as parameter to the resultdialogs saveMeasuresToArray-function.
458 void CarMainWindow::on_pushButtonShowResultDialog_clicked()
460 result->saveMeasuresToArray(measures);
461 this->result->show();
464 void CarMainWindow::userLogin()
466 myHttpClient->checkLogin();
470 * Resets Accelerometer measurement variables
472 void CarMainWindow::resetAccelerometerMeasurements()
474 currentAcceleration = 0;
475 currentAccelerationString = "";
478 distanceTraveled = "";
479 //firstAcceleration = 0;
482 //lastScreenUpdateInSeconds = 0;
484 reverseAccelerationFlag = false;
486 //accelerometer->stop();
488 vehicleStartedMoving = false;
493 * This function is called to handle checkpoints
494 *@param totalTime total time elapsed since starting measurements
495 *@param currentSpeed current speed of the device
497 void CarMainWindow::handleCheckPoint(double totalTime, double currentSpeed)
499 switch (counterForSaveResults)
502 measures->setTime10kmh(totalTime);
506 measures->setTime20kmh(totalTime);
510 measures->setTime30kmh(totalTime);
514 measures->setTime40kmh(totalTime);
518 measures->setTime50kmh(totalTime);
522 measures->setTime60kmh(totalTime);
526 measures->setTime70kmh(totalTime);
530 measures->setTime80kmh(totalTime);
534 measures->setTime90kmh(totalTime);
538 measures->setTime100kmh(totalTime);
544 counterForSaveResults++;
546 if (choiceInt == 0 && measures->getTime40kmh() != 0)
548 setTimeAxisGapAndShowResult(measures->getTime40kmh());
550 this->accelerometerTimer->stop();
553 counterForSaveResults = 0;
555 else if (choiceInt == 1 && measures->getTime100kmh() != 0)
557 setTimeAxisGapAndShowResult(measures->getTime100kmh());
559 this->accelerometerTimer->stop();
562 counterForSaveResults = 0;
564 else if (choiceInt == 2 && measures->getTime10kmh() != 0)
566 setTimeAxisGapAndShowResult(measures->getTime10kmh());
568 this->accelerometerTimer->stop();
571 counterForSaveResults = 0;
573 else if (choiceInt != 1 && choiceInt != 0 && measures->getTime80kmh() != 0)
575 setTimeAxisGapAndShowResult(measures->getTime80kmh());
577 this->accelerometerTimer->stop();
580 counterForSaveResults = 0;
584 qDebug() << "something wrong in handleCheckPoint()";
589 *This function is called to read (and process) data from the accelerometer
591 void CarMainWindow::readAccelerometerData()
594 double changeInAcceleration = 0;
597 accelerometer->getAcceleration(x, y, z);
599 // keep the following line as close to the SetKinematicsProperties method as possible
600 currentTime = stopWatch.elapsed();
602 //accelerometer->smoothData(x, y, z);
605 movingAverageZ->Enqueue(z);
606 z = movingAverageZ->Average();
609 x -= accelerometer->getCalibrationX();
610 y -= accelerometer->getCalibrationY();
611 z -= accelerometer->getCalibrationZ();
613 QString str = QString("acc x: " + QString::number(x) + "\n" +
614 "acc y: " + QString::number(y) + "\n" +
615 "acc z: " + QString::number(z) + "\n");
617 currentAcceleration = z;//sqrt(x*x + y*y + z*z);
618 changeInAcceleration = currentAcceleration;
620 if (((fabs(changeInAcceleration) <= accelerationStartThreshold)
621 && !vehicleStartedMoving))
625 else if(!vehicleStartedMoving)
627 vehicleStartedMoving = true;
633 calculate->calculateParameters(changeInAcceleration, (currentTime - previousTime)/1000);
634 previousTime = currentTime;
636 s.sprintf("%.2f", changeInAcceleration);
637 currentAccelerationString = s;
640 speed = calculate->getCurrentSpeed();
641 speed = speed*3.6;//((speed*1000)/kSecondsInHour);
642 s.sprintf("%.1f", speed);
645 s.sprintf("%.2f", calculate->getDistanceTraveled());
646 distanceTraveled = s;
652 time = calculate->getTotalTime();
654 s.sprintf("%.2f", time);
657 str.append("ca: " + currentAccelerationString + " G\n" );
658 str.append("cspeed: " + currentSpeed + " km/h \n" );
659 str.append("dist: " + distanceTraveled + " m \n" );
660 str.append("time: " + totalTime + " s \n" );
662 if ((stopTime > 0) && (previousTime >= stopTime))
664 // we want to end at a stopping point that the user chose
666 resetAccelerometerMeasurements();
671 *This function is used to calibrate accelerometer
673 void CarMainWindow::calibrateAccelerometer()
675 resetAccelerometerMeasurements();
676 accelerometer->calibrate();
680 *This slot function is called when GPS on checkbox state changed. Route-tab view.
683 void CarMainWindow::on_gpsOnCheckBox_stateChanged(int GPSState)
685 //Stop polling GPS. Route-tab view.
688 ui->labelRouteTabGPSStatus->setText("GPS status: GPS off");
689 location->stopPollingGPS();
693 //Start polling GPS. Route-tab view.
696 ui->labelRouteTabGPSStatus->setText("GPS status: GPS on");
697 location->startPollingGPS();
702 *This slot function is called when GPS status changed. Route- and measure-tab view.
704 void CarMainWindow::gpsStatus()
706 //IF GPS checkbox is ON
707 if (ui->gpsOnCheckBox->isChecked())
709 //If GPS find 4 satellite.
710 if (location->getSatellitesInUse() >= 4)
712 //Set gps status. Route-tab view.
713 ui->labelRouteTabGPSStatus->setText("GPS ready");
715 //Set time. Route-tab view.
716 gpsTime->setTime_t(location->getTime());
717 QString gpsDateNow = gpsTime->toString("dd.MM.yyyy hh:mm:ss");
718 ui->labelRouteTabGPSTime->setText("GPS time: " + gpsDateNow);
720 //Set latitude & longitude. Route-tab view.
721 ui->labelRouteTabLatitude->setText("Latitude: " + QString::number(location->getLatitude()));
722 ui->labelRouteTabLongitude->setText("Longitude: " + QString::number(location->getLongitude()));
724 //Set rec status. Route-tab view.
725 if (ui->startRecPushButton->text() == "Stop recording")
727 ui->labelRouteTabRecStatus->setText("Recorded " + QString::number(gpsData->roundCounter) + " point");
730 //Get speed. Route- and Measure-tab view.
731 gpsSpeed = location->getSpeed();
733 //Set speed. Route-tab view.
734 ui->labelRouteTabSpeed->setText("Speed:" + QString::number(gpsSpeed) + "km/h +/-" + QString::number(location->getEps()) + "km/h");
739 ui->labelMeasureTabSpeed->setText(QString::number(gpsSpeed)); //Set speed. //Measure-tab view.
740 ui->labelMeasureTabTime->setText(QString::number(timeFromGps)); //Set time. //Measure-tab view.
745 timer->stop(); //Measure timer
746 ui->labelMeasureTabResult->setText(QString::number(timeFromGps));
747 ui->labelMeasureTabResult->show();
748 ui->pushButtonShowResultDialog->setEnabled(true);
749 ui->pushButtonShowResultDialog->setEnabled(true);
753 //If GPS find less than 4 satellite.
756 ui->labelRouteTabGPSStatus->setText("GPS status: Waiting for GPS");
766 *This slot function is called when gps timer timeout(10ms).
768 void CarMainWindow::gpsTimerTimeout()
773 //IF time is 1 second
774 if (time1000ms == 1000)
776 //Calculate acceleration 1/s
777 gpsSpeedPrevious = gpsSpeedNow; //Previous speed
778 gpsSpeedNow = (location->getSpeed())/3.6; //Speed now (m/s)
779 gpsAcceleration = (gpsSpeedNow - gpsSpeedPrevious)/1; //Calculate acceleration: speed now - previous speed / 1s.
780 //Set acceleration. Route-tab view.
781 ui->labelRouteTabAcceleration->setText("Acceleration: " + QString::number( gpsAcceleration ) + " m/s2");
785 //Set GPS update time. Route-tab view.
786 ui->labelRouteTabGPSUpdateTime->setText("GPS update time: " + QString::number(gpsUpdateTime) + " ms");
790 *This slot function is called when start rec push button clicked. Route-tab view.
792 void CarMainWindow::on_startRecPushButton_clicked()
794 //Start route recording.
795 if (ui->startRecPushButton->text() == "Start recording")
797 ui->startRecPushButton->setText("Stop recording");
798 ui->labelRouteTabRecStatus->setText("Recording started");
799 gpsData->startRouteRecording(ui->labelRouteTabGPSTime->text());
802 //Stop route recording.
803 else if (ui->startRecPushButton->text() == "Stop recording")
805 ui->startRecPushButton->setText("Start recording");
806 ui->labelRouteTabRecStatus->setText("Recording stopped");
807 gpsData->stopRouteRecording(ui->labelRouteTabGPSTime->text());
812 *Sets time axis right way in result dialog and shows target speed result.
813 *@param double pTime is the target speed result time which is shown to the user.
815 void CarMainWindow::setTimeAxisGapAndShowResult(double pTime)
817 ui->pushButtonShowResultDialog->setEnabled(true);
818 ui->pushButtonSendResult->setEnabled(true);
820 timeInteger.setNum(pTime);
821 ui->labelMeasureTabResult->show();
822 ui->labelMeasureTabResult->setText(timeInteger);
824 if (floor(pTime) <= 5)
826 result->setDiagramGapHorizontal(80);
829 else if (floor(pTime) <= 10)
831 result->setDiagramGapHorizontal(40);
836 result->setDiagramGapHorizontal(20);
840 void CarMainWindow::on_calibrateButton_clicked()
842 ui->autoStartButton->setEnabled(true);
843 ui->manualStartButton->setEnabled(true);
845 this->accelerometer->calibrate();