diff --git a/gps_vcones/MainWindow.py b/gps_vcones/MainWindow.py new file mode 100644 index 0000000..4d0ac1a --- /dev/null +++ b/gps_vcones/MainWindow.py @@ -0,0 +1,253 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'mainwindow.ui' +## +## Created by: Qt User Interface Compiler version 5.15.2 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide2.QtCore import * +from PySide2.QtGui import * +from PySide2.QtWidgets import * + + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + if not MainWindow.objectName(): + MainWindow.setObjectName(u"MainWindow") + MainWindow.resize(772, 451) + self.centralwidget = QWidget(MainWindow) + self.centralwidget.setObjectName(u"centralwidget") + self.label_2 = QLabel(self.centralwidget) + self.label_2.setObjectName(u"label_2") + self.label_2.setGeometry(QRect(389, 60, 81, 16)) + self.listCones2 = QListWidget(self.centralwidget) + self.listCones2.setObjectName(u"listCones2") + self.listCones2.setGeometry(QRect(200, 110, 180, 220)) + self.label = QLabel(self.centralwidget) + self.label.setObjectName(u"label") + self.label.setGeometry(QRect(389, 40, 81, 16)) + self.label_3 = QLabel(self.centralwidget) + self.label_3.setObjectName(u"label_3") + self.label_3.setGeometry(QRect(579, 40, 61, 16)) + self.txtLongitude = QLabel(self.centralwidget) + self.txtLongitude.setObjectName(u"txtLongitude") + self.txtLongitude.setGeometry(QRect(470, 60, 91, 20)) + self.txtLongitude.setFrameShape(QFrame.Panel) + self.txtLongitude.setFrameShadow(QFrame.Sunken) + self.txtDist4 = QLabel(self.centralwidget) + self.txtDist4.setObjectName(u"txtDist4") + self.txtDist4.setGeometry(QRect(709, 90, 51, 20)) + self.txtDist4.setFrameShape(QFrame.Panel) + self.txtDist4.setFrameShadow(QFrame.Sunken) + self.txtDist2 = QLabel(self.centralwidget) + self.txtDist2.setObjectName(u"txtDist2") + self.txtDist2.setGeometry(QRect(329, 90, 51, 20)) + self.txtDist2.setFrameShape(QFrame.Panel) + self.txtDist2.setFrameShadow(QFrame.Sunken) + self.txtSpeed = QLabel(self.centralwidget) + self.txtSpeed.setObjectName(u"txtSpeed") + self.txtSpeed.setGeometry(QRect(650, 40, 81, 18)) + self.txtSpeed.setFrameShape(QFrame.Panel) + self.txtSpeed.setFrameShadow(QFrame.Sunken) + self.txtDist1 = QLabel(self.centralwidget) + self.txtDist1.setObjectName(u"txtDist1") + self.txtDist1.setGeometry(QRect(139, 90, 51, 20)) + self.txtDist1.setFrameShape(QFrame.Panel) + self.txtDist1.setFrameShadow(QFrame.Sunken) + self.lblList2 = QLabel(self.centralwidget) + self.lblList2.setObjectName(u"lblList2") + self.lblList2.setGeometry(QRect(200, 90, 141, 16)) + self.lblList1 = QLabel(self.centralwidget) + self.lblList1.setObjectName(u"lblList1") + self.lblList1.setGeometry(QRect(10, 90, 141, 16)) + self.txtLatitude = QLabel(self.centralwidget) + self.txtLatitude.setObjectName(u"txtLatitude") + self.txtLatitude.setGeometry(QRect(470, 40, 91, 20)) + self.txtLatitude.setFrameShape(QFrame.Panel) + self.txtLatitude.setFrameShadow(QFrame.Sunken) + self.label_4 = QLabel(self.centralwidget) + self.label_4.setObjectName(u"label_4") + self.label_4.setGeometry(QRect(579, 60, 61, 16)) + self.listCones4 = QListWidget(self.centralwidget) + self.listCones4.setObjectName(u"listCones4") + self.listCones4.setGeometry(QRect(580, 110, 180, 220)) + self.label_5 = QLabel(self.centralwidget) + self.label_5.setObjectName(u"label_5") + self.label_5.setGeometry(QRect(20, 10, 281, 16)) + font = QFont() + font.setPointSize(14) + self.label_5.setFont(font) + self.exitButton = QPushButton(self.centralwidget) + self.exitButton.setObjectName(u"exitButton") + self.exitButton.setGeometry(QRect(680, 380, 84, 32)) + self.lblList4 = QLabel(self.centralwidget) + self.lblList4.setObjectName(u"lblList4") + self.lblList4.setGeometry(QRect(580, 90, 141, 16)) + self.listCones3 = QListWidget(self.centralwidget) + self.listCones3.setObjectName(u"listCones3") + self.listCones3.setGeometry(QRect(390, 110, 180, 220)) + self.listCones1 = QListWidget(self.centralwidget) + self.listCones1.setObjectName(u"listCones1") + self.listCones1.setGeometry(QRect(10, 110, 180, 220)) + self.txtDist3 = QLabel(self.centralwidget) + self.txtDist3.setObjectName(u"txtDist3") + self.txtDist3.setGeometry(QRect(519, 90, 51, 20)) + self.txtDist3.setFrameShape(QFrame.Panel) + self.txtDist3.setFrameShadow(QFrame.Sunken) + self.txtHeading = QLabel(self.centralwidget) + self.txtHeading.setObjectName(u"txtHeading") + self.txtHeading.setGeometry(QRect(650, 60, 81, 18)) + self.txtHeading.setFrameShape(QFrame.Panel) + self.txtHeading.setFrameShadow(QFrame.Sunken) + self.lblList3 = QLabel(self.centralwidget) + self.lblList3.setObjectName(u"lblList3") + self.lblList3.setGeometry(QRect(390, 90, 141, 16)) + self.openFiles = QPushButton(self.centralwidget) + self.openFiles.setObjectName(u"openFiles") + self.openFiles.setGeometry(QRect(40, 40, 111, 32)) + self.txtTime = QLabel(self.centralwidget) + self.txtTime.setObjectName(u"txtTime") + self.txtTime.setGeometry(QRect(470, 10, 261, 20)) + self.txtTime.setFrameShape(QFrame.Panel) + self.txtTime.setFrameShadow(QFrame.Sunken) + self.label_7 = QLabel(self.centralwidget) + self.label_7.setObjectName(u"label_7") + self.label_7.setGeometry(QRect(390, 10, 49, 16)) + self.logEnabled = QCheckBox(self.centralwidget) + self.logEnabled.setObjectName(u"logEnabled") + self.logEnabled.setGeometry(QRect(170, 50, 131, 20)) + self.addPoint1 = QPushButton(self.centralwidget) + self.addPoint1.setObjectName(u"addPoint1") + self.addPoint1.setGeometry(QRect(60, 330, 41, 32)) + self.delPoint1 = QPushButton(self.centralwidget) + self.delPoint1.setObjectName(u"delPoint1") + self.delPoint1.setGeometry(QRect(100, 340, 41, 32)) + self.addPoint2 = QPushButton(self.centralwidget) + self.addPoint2.setObjectName(u"addPoint2") + self.addPoint2.setGeometry(QRect(250, 330, 41, 32)) + self.delPoint2 = QPushButton(self.centralwidget) + self.delPoint2.setObjectName(u"delPoint2") + self.delPoint2.setGeometry(QRect(290, 340, 41, 32)) + self.addPoint3 = QPushButton(self.centralwidget) + self.addPoint3.setObjectName(u"addPoint3") + self.addPoint3.setGeometry(QRect(440, 330, 41, 32)) + self.delPoint3 = QPushButton(self.centralwidget) + self.delPoint3.setObjectName(u"delPoint3") + self.delPoint3.setGeometry(QRect(480, 340, 41, 32)) + self.addPoint4 = QPushButton(self.centralwidget) + self.addPoint4.setObjectName(u"addPoint4") + self.addPoint4.setGeometry(QRect(630, 330, 41, 32)) + self.delPoint4 = QPushButton(self.centralwidget) + self.delPoint4.setObjectName(u"delPoint4") + self.delPoint4.setGeometry(QRect(670, 340, 41, 32)) + self.saveList1 = QPushButton(self.centralwidget) + self.saveList1.setObjectName(u"saveList1") + self.saveList1.setGeometry(QRect(150, 340, 41, 32)) + self.saveList2 = QPushButton(self.centralwidget) + self.saveList2.setObjectName(u"saveList2") + self.saveList2.setGeometry(QRect(340, 340, 41, 32)) + self.saveList3 = QPushButton(self.centralwidget) + self.saveList3.setObjectName(u"saveList3") + self.saveList3.setGeometry(QRect(530, 340, 41, 32)) + self.saveList4 = QPushButton(self.centralwidget) + self.saveList4.setObjectName(u"saveList4") + self.saveList4.setGeometry(QRect(720, 340, 41, 32)) + self.resetList1 = QPushButton(self.centralwidget) + self.resetList1.setObjectName(u"resetList1") + self.resetList1.setGeometry(QRect(10, 340, 41, 32)) + self.resetList2 = QPushButton(self.centralwidget) + self.resetList2.setObjectName(u"resetList2") + self.resetList2.setGeometry(QRect(200, 340, 41, 32)) + self.resetList3 = QPushButton(self.centralwidget) + self.resetList3.setObjectName(u"resetList3") + self.resetList3.setGeometry(QRect(390, 340, 41, 32)) + self.resetList4 = QPushButton(self.centralwidget) + self.resetList4.setObjectName(u"resetList4") + self.resetList4.setGeometry(QRect(580, 340, 41, 32)) + self.saveConfig = QPushButton(self.centralwidget) + self.saveConfig.setObjectName(u"saveConfig") + self.saveConfig.setGeometry(QRect(340, 380, 84, 32)) + self.insPoint1 = QPushButton(self.centralwidget) + self.insPoint1.setObjectName(u"insPoint1") + self.insPoint1.setGeometry(QRect(60, 360, 41, 32)) + self.insPoint2 = QPushButton(self.centralwidget) + self.insPoint2.setObjectName(u"insPoint2") + self.insPoint2.setGeometry(QRect(250, 360, 41, 32)) + self.insPoint3 = QPushButton(self.centralwidget) + self.insPoint3.setObjectName(u"insPoint3") + self.insPoint3.setGeometry(QRect(440, 360, 41, 32)) + self.insPoint4 = QPushButton(self.centralwidget) + self.insPoint4.setObjectName(u"insPoint4") + self.insPoint4.setGeometry(QRect(630, 360, 41, 32)) + self.txtRange = QLineEdit(self.centralwidget) + self.txtRange.setObjectName(u"txtRange") + self.txtRange.setGeometry(QRect(310, 10, 41, 30)) + self.label_6 = QLabel(self.centralwidget) + self.label_6.setObjectName(u"label_6") + self.label_6.setGeometry(QRect(250, 20, 61, 16)) + MainWindow.setCentralWidget(self.centralwidget) + self.menubar = QMenuBar(MainWindow) + self.menubar.setObjectName(u"menubar") + self.menubar.setGeometry(QRect(0, 0, 772, 28)) + MainWindow.setMenuBar(self.menubar) + self.statusbar = QStatusBar(MainWindow) + self.statusbar.setObjectName(u"statusbar") + MainWindow.setStatusBar(self.statusbar) + + self.retranslateUi(MainWindow) + + QMetaObject.connectSlotsByName(MainWindow) + # setupUi + + def retranslateUi(self, MainWindow): + MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"NTCNA GPS Virtual Cones V1.0", None)) + self.label_2.setText(QCoreApplication.translate("MainWindow", u"Longitude:", None)) + self.label.setText(QCoreApplication.translate("MainWindow", u"Latitude:", None)) + self.label_3.setText(QCoreApplication.translate("MainWindow", u"Speed:", None)) + self.txtLongitude.setText(QCoreApplication.translate("MainWindow", u"0", None)) + self.txtDist4.setText(QCoreApplication.translate("MainWindow", u"0", None)) + self.txtDist2.setText(QCoreApplication.translate("MainWindow", u"0", None)) + self.txtSpeed.setText(QCoreApplication.translate("MainWindow", u"0", None)) + self.txtDist1.setText(QCoreApplication.translate("MainWindow", u"0", None)) + self.lblList2.setText(QCoreApplication.translate("MainWindow", u"TextLabel", None)) + self.lblList1.setText(QCoreApplication.translate("MainWindow", u"TextLabel", None)) + self.txtLatitude.setText(QCoreApplication.translate("MainWindow", u"0", None)) + self.label_4.setText(QCoreApplication.translate("MainWindow", u"Heading:", None)) + self.label_5.setText(QCoreApplication.translate("MainWindow", u"NTCNA GPS Virtual Cones", None)) + self.exitButton.setText(QCoreApplication.translate("MainWindow", u"Exit", None)) + self.lblList4.setText(QCoreApplication.translate("MainWindow", u"TextLabel", None)) + self.txtDist3.setText(QCoreApplication.translate("MainWindow", u"0", None)) + self.txtHeading.setText(QCoreApplication.translate("MainWindow", u"0", None)) + self.lblList3.setText(QCoreApplication.translate("MainWindow", u"TextLabel", None)) + self.openFiles.setText(QCoreApplication.translate("MainWindow", u"Open Files", None)) + self.txtTime.setText("") + self.label_7.setText(QCoreApplication.translate("MainWindow", u"Time:", None)) + self.logEnabled.setText(QCoreApplication.translate("MainWindow", u"Logging Enabled", None)) + self.addPoint1.setText(QCoreApplication.translate("MainWindow", u"Add", None)) + self.delPoint1.setText(QCoreApplication.translate("MainWindow", u"Del", None)) + self.addPoint2.setText(QCoreApplication.translate("MainWindow", u"Add", None)) + self.delPoint2.setText(QCoreApplication.translate("MainWindow", u"Del", None)) + self.addPoint3.setText(QCoreApplication.translate("MainWindow", u"Add", None)) + self.delPoint3.setText(QCoreApplication.translate("MainWindow", u"Del", None)) + self.addPoint4.setText(QCoreApplication.translate("MainWindow", u"Add", None)) + self.delPoint4.setText(QCoreApplication.translate("MainWindow", u"Del", None)) + self.saveList1.setText(QCoreApplication.translate("MainWindow", u"Save", None)) + self.saveList2.setText(QCoreApplication.translate("MainWindow", u"Save", None)) + self.saveList3.setText(QCoreApplication.translate("MainWindow", u"Save", None)) + self.saveList4.setText(QCoreApplication.translate("MainWindow", u"Save", None)) + self.resetList1.setText(QCoreApplication.translate("MainWindow", u"Reset", None)) + self.resetList2.setText(QCoreApplication.translate("MainWindow", u"Reset", None)) + self.resetList3.setText(QCoreApplication.translate("MainWindow", u"Reset", None)) + self.resetList4.setText(QCoreApplication.translate("MainWindow", u"Reset", None)) + self.saveConfig.setText(QCoreApplication.translate("MainWindow", u"SaveConfig", None)) + self.insPoint1.setText(QCoreApplication.translate("MainWindow", u"Ins", None)) + self.insPoint2.setText(QCoreApplication.translate("MainWindow", u"Ins", None)) + self.insPoint3.setText(QCoreApplication.translate("MainWindow", u"Ins", None)) + self.insPoint4.setText(QCoreApplication.translate("MainWindow", u"Ins", None)) + self.txtRange.setText(QCoreApplication.translate("MainWindow", u"3.0", None)) + self.label_6.setText(QCoreApplication.translate("MainWindow", u"Range:", None)) + # retranslateUi + diff --git a/gps_vcones/alert.wav b/gps_vcones/alert.wav new file mode 100644 index 0000000..268ffc0 Binary files /dev/null and b/gps_vcones/alert.wav differ diff --git a/gps_vcones/home-block.csv b/gps_vcones/home-block.csv new file mode 100644 index 0000000..48d89f4 --- /dev/null +++ b/gps_vcones/home-block.csv @@ -0,0 +1,7 @@ + 42.5218830, -83.2373390, 5.0 + 42.5210100, -83.2361230, 5.0 + 42.5211590, -83.2337800, 5.0 + 42.5220680, -83.2337250, 5.0 + 42.5232330, -83.2339910, 5.0 + 42.5226510, -83.2360890, 5.0 + 42.5221890, -83.2371260, 5.0 diff --git a/gps_vcones/mainwindow.ui b/gps_vcones/mainwindow.ui new file mode 100644 index 0000000..ac3b8b4 --- /dev/null +++ b/gps_vcones/mainwindow.ui @@ -0,0 +1,716 @@ + + + MainWindow + + + + 0 + 0 + 772 + 451 + + + + NTCNA GPS Virtual Cones V1.0 + + + + + + 389 + 60 + 81 + 16 + + + + Longitude: + + + + + + 200 + 110 + 180 + 220 + + + + + + + 389 + 40 + 81 + 16 + + + + Latitude: + + + + + + 579 + 40 + 61 + 16 + + + + Speed: + + + + + + 470 + 60 + 91 + 20 + + + + QFrame::Panel + + + QFrame::Sunken + + + 0 + + + + + + 709 + 90 + 51 + 20 + + + + QFrame::Panel + + + QFrame::Sunken + + + 0 + + + + + + 329 + 90 + 51 + 20 + + + + QFrame::Panel + + + QFrame::Sunken + + + 0 + + + + + + 650 + 40 + 81 + 18 + + + + QFrame::Panel + + + QFrame::Sunken + + + 0 + + + + + + 139 + 90 + 51 + 20 + + + + QFrame::Panel + + + QFrame::Sunken + + + 0 + + + + + + 200 + 90 + 141 + 16 + + + + TextLabel + + + + + + 10 + 90 + 141 + 16 + + + + TextLabel + + + + + + 470 + 40 + 91 + 20 + + + + QFrame::Panel + + + QFrame::Sunken + + + 0 + + + + + + 579 + 60 + 61 + 16 + + + + Heading: + + + + + + 580 + 110 + 180 + 220 + + + + + + + 20 + 10 + 281 + 16 + + + + + 14 + + + + NTCNA GPS Virtual Cones + + + + + + 680 + 380 + 84 + 32 + + + + Exit + + + + + + 580 + 90 + 141 + 16 + + + + TextLabel + + + + + + 390 + 110 + 180 + 220 + + + + + + + 10 + 110 + 180 + 220 + + + + + + + 519 + 90 + 51 + 20 + + + + QFrame::Panel + + + QFrame::Sunken + + + 0 + + + + + + 650 + 60 + 81 + 18 + + + + QFrame::Panel + + + QFrame::Sunken + + + 0 + + + + + + 390 + 90 + 141 + 16 + + + + TextLabel + + + + + + 40 + 40 + 111 + 32 + + + + Open Files + + + + + + 470 + 10 + 261 + 20 + + + + QFrame::Panel + + + QFrame::Sunken + + + + + + + + + 390 + 10 + 49 + 16 + + + + Time: + + + + + + 170 + 50 + 131 + 20 + + + + Logging Enabled + + + + + + 60 + 330 + 41 + 32 + + + + Add + + + + + + 100 + 340 + 41 + 32 + + + + Del + + + + + + 250 + 330 + 41 + 32 + + + + Add + + + + + + 290 + 340 + 41 + 32 + + + + Del + + + + + + 440 + 330 + 41 + 32 + + + + Add + + + + + + 480 + 340 + 41 + 32 + + + + Del + + + + + + 630 + 330 + 41 + 32 + + + + Add + + + + + + 670 + 340 + 41 + 32 + + + + Del + + + + + + 150 + 340 + 41 + 32 + + + + Save + + + + + + 340 + 340 + 41 + 32 + + + + Save + + + + + + 530 + 340 + 41 + 32 + + + + Save + + + + + + 720 + 340 + 41 + 32 + + + + Save + + + + + + 10 + 340 + 41 + 32 + + + + Reset + + + + + + 200 + 340 + 41 + 32 + + + + Reset + + + + + + 390 + 340 + 41 + 32 + + + + Reset + + + + + + 580 + 340 + 41 + 32 + + + + Reset + + + + + + 340 + 380 + 84 + 32 + + + + SaveConfig + + + + + + 60 + 360 + 41 + 32 + + + + Ins + + + + + + 250 + 360 + 41 + 32 + + + + Ins + + + + + + 440 + 360 + 41 + 32 + + + + Ins + + + + + + 630 + 360 + 41 + 32 + + + + Ins + + + + + + 310 + 10 + 41 + 30 + + + + 3.0 + + + + + + 250 + 20 + 61 + 16 + + + + Range: + + + + + + + 0 + 0 + 772 + 28 + + + + + + + + diff --git a/gps_vcones/ublox-6h-250ms.txt b/gps_vcones/ublox-6h-250ms.txt new file mode 100644 index 0000000..95f8ac3 --- /dev/null +++ b/gps_vcones/ublox-6h-250ms.txt @@ -0,0 +1,71 @@ +MON-VER - 0A 04 28 00 37 2E 30 33 20 28 34 35 39 36 39 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 30 30 30 34 30 30 30 37 00 00 +CFG-ANT - 06 13 04 00 1B 00 8B A9 +CFG-DAT - 06 06 02 00 00 00 +CFG-FXN - 06 0E 24 00 0C 00 00 00 00 00 00 00 00 00 00 00 10 27 00 00 10 27 00 00 D0 07 00 00 18 FC FF FF 00 00 00 00 00 00 00 00 +CFG-INF - 06 02 0A 00 00 00 00 00 00 00 00 00 00 00 +CFG-INF - 06 02 0A 00 01 00 00 00 87 87 87 87 87 87 +CFG-INF - 06 02 0A 00 03 00 00 00 00 00 00 00 00 00 +CFG-ITFM - 06 39 08 00 F3 AC 62 2D 1E 03 00 00 +CFG-MSG - 06 01 08 00 0B 30 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0B 32 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0B 33 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0B 31 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0B 01 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0B 00 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0A 0B 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0A 09 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0A 02 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0A 06 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0A 07 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0A 21 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0A 08 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 60 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 22 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 31 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 04 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 01 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 02 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 32 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 06 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 03 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 30 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 20 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 21 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 11 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 12 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 02 20 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0D 03 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0D 01 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0D 06 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 F0 00 01 01 01 01 01 01 +CFG-MSG - 06 01 08 00 F0 01 01 01 01 01 01 01 +CFG-MSG - 06 01 08 00 F0 02 01 01 01 01 01 01 +CFG-MSG - 06 01 08 00 F0 03 01 01 01 01 01 01 +CFG-MSG - 06 01 08 00 F0 04 01 01 01 01 01 01 +CFG-MSG - 06 01 08 00 F0 05 01 01 01 01 01 01 +CFG-MSG - 06 01 08 00 F0 06 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 F0 07 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 F0 08 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 F0 09 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 F0 0A 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 F1 00 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 F1 03 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 F1 04 00 00 00 00 00 00 +CFG-NAV5 - 06 24 24 00 FF FF 00 03 00 00 00 00 10 27 00 00 05 00 FA 00 FA 00 64 00 2C 01 00 3C 00 00 00 00 00 00 00 00 00 00 00 00 +CFG-NAVX5 - 06 23 28 00 00 00 FF FF 43 00 00 00 03 02 03 10 07 00 00 01 00 00 43 06 00 00 00 00 01 01 00 00 00 64 78 00 00 00 00 00 00 00 00 00 +CFG-NMEA - 06 17 04 00 00 23 00 02 +CFG-PM - 06 32 18 00 00 06 00 00 04 90 00 00 E8 03 00 00 10 27 00 00 00 00 00 00 02 00 00 00 +CFG-PM2 - 06 3B 2C 00 01 06 00 00 00 90 02 00 E8 03 00 00 10 27 00 00 00 00 00 00 02 00 00 00 2C 01 00 00 4F C1 03 00 86 02 00 00 FE 00 00 00 64 40 01 00 +CFG-PRT - 06 00 14 00 00 00 00 00 84 00 00 00 00 00 00 00 07 00 07 00 00 00 00 00 +CFG-PRT - 06 00 14 00 01 00 00 00 C0 08 00 00 00 C2 01 00 07 00 03 00 00 00 00 00 +CFG-PRT - 06 00 14 00 02 00 00 00 C0 08 00 00 80 25 00 00 00 00 00 00 00 00 00 00 +CFG-PRT - 06 00 14 00 03 00 00 00 00 00 00 00 00 00 00 00 07 00 07 00 00 00 00 00 +CFG-PRT - 06 00 14 00 04 00 00 00 00 32 00 00 00 00 00 00 07 00 07 00 00 00 00 00 +CFG-RATE - 06 08 06 00 FA 00 01 00 01 00 +CFG-RINV - 06 34 18 00 00 4E 6F 74 69 63 65 3A 20 6E 6F 20 64 61 74 61 20 73 61 76 65 64 21 00 +CFG-RXM - 06 11 02 00 08 00 +CFG-SBAS - 06 16 08 00 01 03 03 00 51 62 06 00 +CFG-TP - 06 07 14 00 40 42 0F 00 A0 86 01 00 01 01 00 00 32 00 00 00 00 00 00 00 +CFG-TP5 - 06 31 20 00 00 07 40 00 32 00 00 00 40 42 0F 00 40 42 0F 00 00 00 00 00 A0 86 01 00 00 00 00 00 F7 00 00 00 +CFG-TP5 - 06 31 20 00 01 07 40 00 32 00 00 00 04 00 00 00 01 00 00 00 48 E8 01 00 A0 86 01 00 00 00 00 00 FE 00 00 00 +CFG-USB - 06 1B 6C 00 46 15 A6 01 00 00 00 00 64 00 00 00 75 2D 62 6C 6F 78 20 41 47 20 2D 20 77 77 77 2E 75 2D 62 6C 6F 78 2E 63 6F 6D 00 00 00 00 00 00 75 2D 62 6C 6F 78 20 36 20 20 2D 20 20 47 50 53 20 52 65 63 65 69 76 65 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/gps_vcones/ublox-6h-500ms.txt b/gps_vcones/ublox-6h-500ms.txt new file mode 100644 index 0000000..f435b71 --- /dev/null +++ b/gps_vcones/ublox-6h-500ms.txt @@ -0,0 +1,71 @@ +MON-VER - 0A 04 28 00 37 2E 30 33 20 28 34 35 39 36 39 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 30 30 30 34 30 30 30 37 00 00 +CFG-ANT - 06 13 04 00 1B 00 8B A9 +CFG-DAT - 06 06 02 00 00 00 +CFG-FXN - 06 0E 24 00 0C 00 00 00 00 00 00 00 00 00 00 00 10 27 00 00 10 27 00 00 D0 07 00 00 18 FC FF FF 00 00 00 00 00 00 00 00 +CFG-INF - 06 02 0A 00 00 00 00 00 00 00 00 00 00 00 +CFG-INF - 06 02 0A 00 01 00 00 00 87 87 87 87 87 87 +CFG-INF - 06 02 0A 00 03 00 00 00 00 00 00 00 00 00 +CFG-ITFM - 06 39 08 00 F3 AC 62 2D 1E 03 00 00 +CFG-MSG - 06 01 08 00 0B 30 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0B 32 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0B 33 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0B 31 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0B 01 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0B 00 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0A 0B 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0A 09 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0A 02 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0A 06 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0A 07 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0A 21 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0A 08 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 60 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 22 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 31 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 04 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 01 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 02 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 32 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 06 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 03 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 30 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 20 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 21 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 11 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 01 12 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 02 20 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0D 03 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0D 01 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 0D 06 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 F0 00 01 01 01 01 01 01 +CFG-MSG - 06 01 08 00 F0 01 01 01 01 01 01 01 +CFG-MSG - 06 01 08 00 F0 02 01 01 01 01 01 01 +CFG-MSG - 06 01 08 00 F0 03 01 01 01 01 01 01 +CFG-MSG - 06 01 08 00 F0 04 01 01 01 01 01 01 +CFG-MSG - 06 01 08 00 F0 05 01 01 01 01 01 01 +CFG-MSG - 06 01 08 00 F0 06 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 F0 07 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 F0 08 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 F0 09 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 F0 0A 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 F1 00 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 F1 03 00 00 00 00 00 00 +CFG-MSG - 06 01 08 00 F1 04 00 00 00 00 00 00 +CFG-NAV5 - 06 24 24 00 FF FF 00 03 00 00 00 00 10 27 00 00 05 00 FA 00 FA 00 64 00 2C 01 00 3C 00 00 00 00 00 00 00 00 00 00 00 00 +CFG-NAVX5 - 06 23 28 00 00 00 FF FF 43 00 00 00 03 02 03 10 07 00 00 01 00 00 43 06 00 00 00 00 01 01 00 00 00 64 78 00 00 00 00 00 00 00 00 00 +CFG-NMEA - 06 17 04 00 00 23 00 02 +CFG-PM - 06 32 18 00 00 06 00 00 04 90 00 00 E8 03 00 00 10 27 00 00 00 00 00 00 02 00 00 00 +CFG-PM2 - 06 3B 2C 00 01 06 00 00 00 90 02 00 E8 03 00 00 10 27 00 00 00 00 00 00 02 00 00 00 2C 01 00 00 4F C1 03 00 86 02 00 00 FE 00 00 00 64 40 01 00 +CFG-PRT - 06 00 14 00 00 00 00 00 84 00 00 00 00 00 00 00 07 00 07 00 00 00 00 00 +CFG-PRT - 06 00 14 00 01 00 00 00 C0 08 00 00 00 C2 01 00 07 00 03 00 00 00 00 00 +CFG-PRT - 06 00 14 00 02 00 00 00 C0 08 00 00 80 25 00 00 00 00 00 00 00 00 00 00 +CFG-PRT - 06 00 14 00 03 00 00 00 00 00 00 00 00 00 00 00 07 00 07 00 00 00 00 00 +CFG-PRT - 06 00 14 00 04 00 00 00 00 32 00 00 00 00 00 00 07 00 07 00 00 00 00 00 +CFG-RATE - 06 08 06 00 F4 01 01 00 01 00 +CFG-RINV - 06 34 18 00 00 4E 6F 74 69 63 65 3A 20 6E 6F 20 64 61 74 61 20 73 61 76 65 64 21 00 +CFG-RXM - 06 11 02 00 08 00 +CFG-SBAS - 06 16 08 00 01 03 03 00 51 62 06 00 +CFG-TP - 06 07 14 00 40 42 0F 00 A0 86 01 00 01 01 00 00 32 00 00 00 00 00 00 00 +CFG-TP5 - 06 31 20 00 00 07 40 00 32 00 00 00 40 42 0F 00 40 42 0F 00 00 00 00 00 A0 86 01 00 00 00 00 00 F7 00 00 00 +CFG-TP5 - 06 31 20 00 01 07 40 00 32 00 00 00 04 00 00 00 01 00 00 00 48 E8 01 00 A0 86 01 00 00 00 00 00 FE 00 00 00 +CFG-USB - 06 1B 6C 00 46 15 A6 01 00 00 00 00 64 00 00 00 75 2D 62 6C 6F 78 20 41 47 20 2D 20 77 77 77 2E 75 2D 62 6C 6F 78 2E 63 6F 6D 00 00 00 00 00 00 75 2D 62 6C 6F 78 20 36 20 20 2D 20 20 47 50 53 20 52 65 63 65 69 76 65 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/gps_vcones/virtual_cones.py b/gps_vcones/virtual_cones.py new file mode 100755 index 0000000..65083e5 --- /dev/null +++ b/gps_vcones/virtual_cones.py @@ -0,0 +1,278 @@ +#! /usr/bin/python3 + +import os +import sys +import getopt +import csv + +from math import * +from gps import * +from time import strftime, sleep + +import os +from sys import platform + +############################################################################## +# audio stuff +############################################################################## + +sound_args = "" + +def play_sound(file): + if platform == "win32" or platform == "win64" or platform == "cygwin": + cmd = "wmplayer " + '"' + file + '"' + else: + cmd = "aplay -N " + sound_args + " " + file + " &" +# print(cmd) + os.system(cmd) + +############################################################################## +# buzzer stuff +############################################################################## + +# https://www.instructables.com/Raspberry-Pi-Tutorial-How-to-Use-a-Buzzer/ + +try: + import RPi.GPIO as GPIO + + buzzer=23 + seconds=3 + + def buzzer_init(): + GPIO.setwarnings(0) + GPIO.setmode(GPIO.BCM) + GPIO.setup(buzzer, GPIO.OUT) + + def buzzer_on(): + GPIO.output(buzzer, GPIO.HIGH) + + def buzzer_off(): + GPIO.output(buzzer, GPIO.LOW) + + def buzzer_run(): + global seconds + sec = seconds + while (sec): + buzzer_on() + sleep(0.5) + buzzer_off() + sleep(0.5) + sec = sec - 1 + + buzzer_init() +except: + print("Not a Raspberry Pi! No buzzer support.") + +############################################################################## +# gps stuff +############################################################################## + +# https://ozzmaker.com/using-python-with-a-gps-receiver-on-a-raspberry-pi/ + +gpsd = gps(mode=WATCH_ENABLE|WATCH_NEWSTYLE) + +# +# GPS receiver is ublox from V2V-MD at 10x seconds +# + +# http://www.movable-type.co.uk/scripts/latlong.html + +earth_flatening = 1.0/298.257223563 +earth_radius = 6378137.0 + +def roydistance(lat1, lon1, lat2, lon2): + """ + Calculate the great circle distance between two points + on the earth (specified in decimal degrees) + """ + # convert decimal degrees to radians + lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2]) + + # Roy's method + f1 = (1.0 - earth_flatening) + + top = (pow((lon2-lon1), 2) * pow(cos(lat1), 2)) + pow(lat2-lat1, 2) + bot = pow(sin(lat1), 2) + (pow(f1, 2) * pow(cos(lat1), 2)) + + return f1 * earth_radius * sqrt(top/bot) + +############################################################################## +# log +############################################################################## + +debug_on = 0 + +if not os.path.isdir("logs"): + os.mkdir("logs") +log = open(strftime("logs/way-%Y%m%d-%H%M.log"), 'a') +log.write("Time,Latitude,Longitude,Heading,Speed,Description\n") + +############################################################################## +# virtual cones +############################################################################## + +# node from csv (each line is lat, long, distance, next code# (optional)): +# 42.522040, -83.237594, 5, 1 + + +############################################################################## +# class +############################################################################## + +class VirtualCones(): + def __init__(self): + self.filename = "" + self.cones = [] + self.num_cones = 0 + self.current_cone = 0 + self.distance = 0.0 + self.buzz_no = 0 + self.max_buzz = 1 + + def clr_cones(self): + self.cones = [] + self.num_cones = 0 + self.current_cone = 0 + + def add_cone(self, lat, lon, rad): + self.cones.append( [float(lat), float(lon), float(rad)] ) + self.num_cones += 1 + + def read_csv(self, csv_file): + file_csv = open(csv_file) + data_csv = csv.reader(file_csv) + return list(data_csv) + + def read_list(self, file): + self.filename = file + self.clr_cones() + self.cones = self.read_csv(file) + if len(self.cones) == 0: + return + for i in range(0, len(self.cones)): + for j in range(0, 3): + self.cones[i][j] = float(self.cones[i][j]) + self.num_cones = len(self.cones) + return self.cones + + def save_list(self, filename): + with open(filename, "w") as file: + for i in range(0, self.num_cones): + file.write("%11.7f, %11.7f, %4.1f\n" % (self.cones[i][0], self.cones[i][1], self.cones[i][2])) + file.close() + + def check_list(self, lat, lon, heading, speed): + trig = 0 + if self.num_cones == 0: + return (0, 999.0, 0) + + # end of list? + if self.current_cone >= self.num_cones: + self.current_cone = 0 + self.buzz_no = 0 + + # check first node for reset + if self.current_cone: + # node from csv (each line is lat, long, distance) + row = self.cones[0] + cone_lat = row[0] + cone_lon = row[1] + cone_dist = row[2] + dist = roydistance(lat, lon, cone_lat, cone_lon) + if dist < cone_dist: + self.current_cone = 0 + + # node from csv (each line is lat, long, distance, next code#) + row = self.cones[self.current_cone] + cone_lat = row[0] + cone_lon = row[1] + cone_dist = row[2] + + # next cone + cone_next = self.current_cone + 1 + try: + cone_next = int(row[3]) + except: + pass + + # distance between vehicle and cone + self.distance = roydistance(lat, lon, cone_lat, cone_lon) + + # check distance trigger + if self.distance < cone_dist: +# out = "Waypoint %s:%d reached: %f, %f, %f, %d" % (self.filename, self.current_cone, lat, lon, heading, speed) +# print(out) + if self.buzz_no < self.max_buzz: + play_sound("alert.wav") + self.buzz_no = self.buzz_no + 1 + self.current_cone = cone_next + trig = 1 + else: + self.buzz_no = 0 + + return (self.current_cone, self.distance, trig) + +############################################################################## +# main +############################################################################## + +opt_list = "d" + +def main(argv): + global log, debug_on + virtual_list = [[],[],[],[],[],[],[],[],[]] + virtual_count = 0 + + try: + opts, args = getopt.getopt(argv, opt_list, ["",""]) + except getopt.GetoptError: + print(sys.argv[0], '[-d] ') + sys.exit(2) + + for opt, arg in opts: + if opt in ('-h'): + print("virtual_cone_alert.py " + opt_list + " ") + sys.exit() + elif opt in ('-d'): + debug_on = 1 + else: + print("Argument error!") + print("virtual_cone_alert.py " + opt_list + " ") + sys.exit() + + # slurp in files for each list + for arg in args: + try: + cones = VirtualCones() + cones.read_list(arg) + virtual_list[virtual_count] = cones + virtual_count += 1 + except: + print("File open/read failed: ", arg) + sys.exit(1) + + try: + while True: + report = gpsd.next() # + if report['class'] == 'TPV': + + time = getattr(report, 'time', 0.0) + lat = getattr(report, 'lat', 0.0) + lon = getattr(report, 'lon', 0.0) + heading = getattr(report, 'track', 0.0) + speed = getattr(report, 'speed', 0.0) + + log.write("%s,%f,%f,%f,%f\n" % (time, lat, lon, heading, speed)) +# print("Position: %f, %f, %d" % (lat, lon, speed)) + + # walk through each list + for i in range(0, virtual_count): + virtual_list[i].check_list(lat, lon, heading, speed) + +# time.sleep(0.2) + + except (KeyboardInterrupt, SystemExit): #when you press ctrl+c + log.close() + print("Done.\nExiting.") + +main(sys.argv[1:]) diff --git a/gps_vcones/virtual_cones_gui.py b/gps_vcones/virtual_cones_gui.py new file mode 100755 index 0000000..e9b1317 --- /dev/null +++ b/gps_vcones/virtual_cones_gui.py @@ -0,0 +1,524 @@ +#! /usr/bin/python3 + +from sys import platform +from os import path, mkdir, system + +from math import * +from gps import * +from datetime import datetime +from time import time, strftime + +import gpxpy +import csv +import yaml + +from PySide2.QtGui import * +from PySide2.QtWidgets import QApplication, QMainWindow, QFileDialog +from PySide2.QtCore import QObject, Slot, Signal, QThread, QDir + +from MainWindow import Ui_MainWindow + +############################################################################## +# audio stuff +############################################################################## + +sound_args = "" + +def play_sound(file): + if platform == "win32" or platform == "win64" or platform == "cygwin": + cmd = "wmplayer " + '"' + file + '"' + else: + cmd = "aplay -N " + sound_args + " " + file + " &" +# print(cmd) + system(cmd) + +############################################################################## +# gps stuff +############################################################################## + +# https://ozzmaker.com/using-python-with-a-gps-receiver-on-a-raspberry-pi/ + +# +# GPS receiver is ublox from V2V-MD at 10x seconds +# + +# http://www.movable-type.co.uk/scripts/latlong.html + +earth_flatening = 1.0/298.257223563 +earth_radius = 6378137.0 + +def roydistance(lat1, lon1, lat2, lon2): + """ + Calculate the great circle distance between two points + on the earth (specified in decimal degrees) + """ + # convert decimal degrees to radians + lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2]) + + # Roy's method + f1 = (1.0 - earth_flatening) + + top = (pow((lon2-lon1), 2) * pow(cos(lat1), 2)) + pow(lat2-lat1, 2) + bot = pow(sin(lat1), 2) + (pow(f1, 2) * pow(cos(lat1), 2)) + + return f1 * earth_radius * sqrt(top/bot) + +############################################################################## +# log +############################################################################## + +if not path.isdir("logs"): + mkdir("logs") + +############################################################################## +# virtual cones +############################################################################## + +# node from csv (each line is lat, long, distance, next code# (optional)): +# 42.522040, -83.237594, 5, 1 + +############################################################################## +# class +############################################################################## + +class VirtualCones(): + def __init__(self): + self.filename = "" + self.cones = [] + self.num_cones = 0 + self.current_cone = 0 + self.distance = 0.0 + self.buzz_no = 0 + self.max_buzz = 1 + + def clr_cones(self): + self.cones = [] + self.num_cones = 0 + self.current_cone = 0 + + def add_cone(self, lat, lon, rad): + self.cones.append( [float(lat), float(lon), float(rad)] ) + self.num_cones += 1 + + def read_csv(self, csv_file): + file_csv = open(csv_file) + data_csv = csv.reader(file_csv) + return list(data_csv) + + def read_list(self, file): + self.filename = file + self.clr_cones() + self.cones = self.read_csv(file) + if len(self.cones) == 0: + return + for i in range(0, len(self.cones)): + for j in range(0, 3): + self.cones[i][j] = float(self.cones[i][j]) + self.num_cones = len(self.cones) + return self.cones + + def save_list(self, filename): + with open(filename, "w") as file: + for i in range(0, self.num_cones): + file.write("%11.7f, %11.7f, %4.1f\n" % (self.cones[i][0], self.cones[i][1], self.cones[i][2])) + file.close() + + def check_list(self, lat, lon, heading, speed): + trig = 0 + if self.num_cones == 0: + return (0, 999.0, 0) + + # end of list? + if self.current_cone >= self.num_cones: + self.current_cone = 0 + self.buzz_no = 0 + + # check first node for reset + if self.current_cone: + # node from csv (each line is lat, long, distance) + row = self.cones[0] + cone_lat = row[0] + cone_lon = row[1] + cone_dist = row[2] + dist = roydistance(lat, lon, cone_lat, cone_lon) + if dist < cone_dist: + self.current_cone = 0 + + # node from csv (each line is lat, long, distance, next code#) + row = self.cones[self.current_cone] + cone_lat = row[0] + cone_lon = row[1] + cone_dist = row[2] + + # next cone + cone_next = self.current_cone + 1 + try: + cone_next = int(row[3]) + except: + pass + + # distance between vehicle and cone + self.distance = roydistance(lat, lon, cone_lat, cone_lon) + + # check distance trigger + if self.distance < cone_dist: +# out = "Waypoint %s:%d reached: %f, %f, %f, %d" % (self.filename, self.current_cone, lat, lon, heading, speed) +# print(out) + if self.buzz_no < self.max_buzz: + play_sound("alert.wav") + self.buzz_no = self.buzz_no + 1 + self.current_cone = cone_next + trig = 1 + else: + self.buzz_no = 0 + + return (self.current_cone, self.distance, trig) + +############################################################################## +# thread +############################################################################## + +gpsd_host = "localhost" +gpsd_report = () + +class DataSignal(QObject): + sig = Signal(int) + +class DataThread(QThread): + def __init__(self, parent=None): + super(DataThread, self).__init__(parent) + self.new_data = DataSignal() +# self.new_data.sig.connect(parent.update_data) + + def run(self): + global gpsd_report + gpsd = gps(host=gpsd_host, mode=WATCH_ENABLE|WATCH_NEWSTYLE) + + while not self.isInterruptionRequested(): + gpsd_report = gpsd.next() # wait for next packet + self.new_data.sig.emit(1) + + def stop(self): + self.requestInterruption() + self.wait() + +############################################################################## +# main +############################################################################## + +class MainWindow(QMainWindow, Ui_MainWindow): + def __init__(self, *args, obj=None, **kwargs): + super(MainWindow, self).__init__(*args, **kwargs) + self.setupUi(self) + +class ConesWindow(MainWindow): + def __init__(self, *args, obj=None, **kwargs): + super(ConesWindow, self).__init__(*args, **kwargs) + + self.setWindowTitle("NTCNA GPS Virtual Cones V1.6") + + self.vlist1 = VirtualCones() + self.vlist2 = VirtualCones() + self.vlist3 = VirtualCones() + self.vlist4 = VirtualCones() + self.vlists = [self.vlist1, self.vlist2, self.vlist3, self.vlist4] + + # button connections + self.openFiles.clicked.connect(self.read_dialog) + self.exitButton.clicked.connect(self.exit_button) + self.resetList1.clicked.connect(self.reset_list1) + self.resetList2.clicked.connect(self.reset_list2) + self.resetList3.clicked.connect(self.reset_list3) + self.resetList4.clicked.connect(self.reset_list4) + self.addPoint1.clicked.connect(self.add_point1) + self.delPoint1.clicked.connect(self.del_point1) + self.insPoint1.clicked.connect(self.ins_point1) + self.addPoint2.clicked.connect(self.add_point2) + self.delPoint2.clicked.connect(self.del_point2) + self.insPoint2.clicked.connect(self.ins_point2) + self.addPoint3.clicked.connect(self.add_point3) + self.delPoint3.clicked.connect(self.del_point3) + self.insPoint3.clicked.connect(self.ins_point3) + self.addPoint4.clicked.connect(self.add_point4) + self.delPoint4.clicked.connect(self.del_point4) + self.insPoint4.clicked.connect(self.ins_point4) + self.saveList1.clicked.connect(self.save_list1) + self.saveList2.clicked.connect(self.save_list2) + self.saveList3.clicked.connect(self.save_list3) + self.saveList4.clicked.connect(self.save_list4) + self.saveConfig.clicked.connect(self.save_config) + + # makes life easier, avoid redundant code + self.labels = [self.lblList1, self.lblList2, self.lblList3, self.lblList4] + self.lists = [self.listCones1, self.listCones2, self.listCones3, self.listCones4] + self.dists = [self.txtDist1, self.txtDist2, self.txtDist3, self.txtDist4] + self.saves = [self.saveList1, self.saveList2, self.saveList3, self.saveList4] + + for i in range(0, 4): + self.saves[i].hide() + + # txtLatitude + self.latitude = 0.0 + self.longitude = 0.0 + + # GPS log + self.gpx = gpxpy.gpx.GPX() + # Create first track in our GPX: + self.gpx_track = gpxpy.gpx.GPXTrack() + self.gpx.tracks.append(self.gpx_track) + # Create first segment in our GPX track: + self.gpx_segment = gpxpy.gpx.GPXTrackSegment() + self.gpx_track.segments.append(self.gpx_segment) + + self.num_points = 0 + self.my_thread = DataThread() + + def read_dialog(self): + filedialog = QFileDialog(self) + filedialog.setDirectory(QDir.currentPath()) + filedialog.setDefaultSuffix("csv") + filedialog.setNameFilter("CSV (*.csv);; all (*.*)") + filedialog.setFileMode(QFileDialog.ExistingFiles) + selected = filedialog.exec() + if selected: + self.load_cones( filedialog.selectedFiles()[0:4] ) + + def write_dialog(self): + filedialog = QFileDialog(self) + filedialog.setDirectory(QDir.currentPath()) + filedialog.setDefaultSuffix("csv") + filedialog.setNameFilter("CSV (*.csv);; all (*.*)") + selected = filedialog.exec() + if selected: + filename = filedialog.selectedFiles()[0] + return filename + return "" + + # slurp in files for each list + def load_cones(self, args): + count = 0 + for i in range(0, 4): + self.labels[i].setText("") + self.lists[i].clear() + self.saves[i].hide() + self.vlists[i].clr_cones() + + for arg in args: + try: + cones = VirtualCones() + cones.read_list(arg) + self.vlists[count] = cones + self.labels[count].setText(path.basename(arg)) + self.lists[count].clear() + + for i in range(0, cones.num_cones): + self.lists[count].addItem("%11.7f, %11.7f" % (cones.cones[i][0], cones.cones[i][1])) + self.lists[count].setCurrentRow(0) + count += 1 + self.show() + except Exception as e: + print(e) + sys.exit(1) + + def start_thread(self): + if not self.my_thread.isRunning(): + self.my_thread.new_data.sig.connect(self.update_data) + self.my_thread.start() + self.my_thread.setTerminationEnabled(True) + + def stop_thread(self): + self.my_thread.stop() + self.my_thread.wait(3) + self.save_log() + + @Slot(list) + def update_data(self, x): + global gpsd_report + report = gpsd_report + + if report['class'] == 'TPV': + status = getattr(report, 'status', 0) + mode = getattr(report, 'mode', 0) + time = getattr(report, 'time', 0) + lat = getattr(report, 'lat', 0.0) + lon = getattr(report, 'lon', 0.0) + elev = getattr(report, 'altHAE', 0.0) # meters + heading = getattr(report, 'track', 0.0) + speed = getattr(report, 'speed', 0.0) # m/sec + self.latitude = lat + self.longitude = lon + +# self.txtStatus.setText(fix_status[status]) +# self.txtMode.setText(fix_mode[mode]) + self.txtTime.setText(time) + self.txtLatitude.setText("%10.7f" %(lat)) + self.txtLongitude.setText("%10.7f" % (lon)) +# self.txtAltitude.setText("%7.2f" % (elev)) + self.txtHeading.setText("%7.2f" % (heading)) + self.txtSpeed.setText("%7.2f" % (speed)) + + for i in range(0, 4): + if self.lists[i].count() == 0: + continue + (cone, dist, trig) = self.vlists[i].check_list(lat, lon, heading, speed) + if trig: + self.lists[i].setCurrentRow(cone) + if dist < 10000.0: + self.dists[i].setText("%6.1f" % (dist)) + else + self.dists[i].setText("OOR") + + if self.logEnabled.isChecked(): + point = gpxpy.gpx.GPXTrackPoint(lat, lon, elevation=elev) + point.time = datetime.now() + self.gpx_segment.points.append(point) + self.num_points += 1 + + self.show() + + def reset_list1(self): + self.listCones1.current_cone = 0 + self.lists[0].setCurrentRow(0) + + def reset_list2(self): + self.listCones2.current_cone = 0 + self.lists[1].setCurrentRow(0) + + def reset_list3(self): + self.listCones3.current_cone = 0 + self.lists[2].setCurrentRow(0) + + def reset_list4(self): + self.listCones4.current_cone = 0 + self.lists[3].setCurrentRow(0) + + def update_list(self, list): + self.vlists[list].clr_cones() + for i in range(0, self.lists[list].count()): + item = self.lists[list].item(i) + txt = item.text() + lat, lon = txt.split(", ") + self.vlists[list].add_cone(lat, lon, float(self.txtRange.text())) + + def add_point(self, list, add): + self.lists[list].insertItem(self.lists[list].currentRow()+add, "%11.7f, %11.7f" % (self.latitude, self.longitude)) + self.saves[list].show() + self.update_list(list) + + def del_point(self, list): + listItems = self.lists[list].selectedItems() + if not listItems: return + for item in listItems: + self.lists[list].takeItem(self.lists[list].row(item)) + self.saves[list].show() + self.update_list(list) + + def save_list(self, list): + filename = self.labels[list].text() + if filename == "": + filename = self.write_dialog() + if filename == "": + return + filename = path.basename(filename) + self.labels[list].setText(filename) + self.vlists[list].save_list(filename) + self.saves[list].hide() + + def add_point1(self): + self.add_point(0, 1) + + def del_point1(self): + self.del_point(0) + + def ins_point1(self): + self.add_point(0, 0) + + def save_list1(self): + self.save_list(0) + + def add_point2(self): + self.add_point(1, 1) + + def del_point2(self): + self.del_point(1) + + def ins_point2(self): + self.add_point(1, 0) + + def save_list2(self): + self.save_list(1) + + def add_point3(self): + self.add_point(2, 1) + + def del_point3(self): + self.del_point(2) + + def ins_point3(self): + self.add_point(2, 0) + + def save_list3(self): + self.save_list(2) + + def add_point4(self): + self.add_point(3, 1) + + def del_point4(self): + self.del_point(3) + + def ins_point4(self): + self.add_point(3, 0) + + def save_list4(self): + self.save_list(3) + + def save_config(self): + with open('config.yaml', 'w') as f: + config = {} + if gpsd_host != "localhost": + config['gpsd_host'] = gpsd_host + config['lists'] = [] + for i in range(0, 4): + if self.labels[i].text() != "": + self.save_list(i) + config['lists'].append( self.labels[i].text() ) + f.write(yaml.dump(config)) + f.close() + + def save_log(self): + if self.num_points: + log = open(strftime("logs/way-%Y%m%d-%H%M.gpx"), 'w') + log.write(self.gpx.to_xml()) + log.close() + + def closeEvent(self, event): + self.stop_thread() + event.accept() + sys.exit(0) + + def exit_button(self): + self.stop_thread() + sys.exit(0) + + +if __name__ == '__main__': + app = QApplication(sys.argv) + + window = ConesWindow() + window.show() + + config = [] + if path.isfile('config.yaml'): + with open('config.yaml') as f: + config = yaml.load(f, Loader=yaml.FullLoader) + if 'gpsd_host' in config: + gpsd_host = config['gpsd_host'] + + if len(sys.argv[1:]): + window.load_cones(sys.argv[1:]) + elif 'lists' in config: + window.load_cones(config['lists']) + + window.start_thread() + ret = app.exec_() + sys.exit(ret)