TransWikia.com

Accessing GPS via PyQGIS

Geographic Information Systems Asked on November 19, 2021

I am looking for a solution to connect a GPS-device on a COM-Port in QGIS 3 using Python. The GPS is working in the QGIS 3 GPS Gui as it should. As there are many changes between QGIS 2 and 3 the examples of accessing a GPS device with Python in QGIS 2 ( Connect / Disconnect GPS device via PyQGIS ) are not working for QGIS 3 anymore.

Examples of working code using the different GPS-classes form QGIS 3 are not available.

Using

from qgis.core import *
QgsGpsDetector.availablePorts()

results in a list of the available ports like:

[('internalGPS', 'Interes GPS'), ('localhost:2947:', 'Lokaler GPSD'), ('COM1', 'COM1: Kommunikationsanschluss'), ('COM6', 'COM6: Standardmäßgige Seriell-über-Bluetooth-Verbindung'), ('COM5', 'COM5: Standardmäßgige Seriell-über-Bluetooth-Verbindung'), ('COM4', 'COM4: ')]

By looking at the API at https://qgis.org/pyqgis/3.0/core/Gps/QgsGpsConnection.html the QgsGpsConnection should be the way to go. In QGIS 3 it is not possible to use a string for the port using QgsGpsConnection. It has to be QIODevice.
So I tried using

from qgis.core import *
from PyQt5.QtSerialPort import QSerialPort
port = QSerialPort("COM5")
QgsGpsConnection(port)

At this point I am stuck.
I used several ways of QgsGpsConnection() like

QgsGpsConnnection.connect(port) 

con = QgsGpsConnection(port)
con.connect()

but I always recieve an TypeError: qgis._core.QgsGpsConnection represents a C++ abstract class and cannot be instantiated .

As I am new to Python in QGIS I do not know how to go on. My goal is to access the XY-Position and the accuracy of the signal.

2 Answers

My GPS test tool for QGIS 3.4 console. To deactivate select another tool:

class GPS(QgsMapTool):
    def __init__(self, iface):
        self.iface=iface
        self.prj=QgsProject().instance()
        self.canvas = self.iface.mapCanvas() 
        super(GPS, self).__init__(self.canvas)
        try:
            self.gps_active = False
            #transformation
            self.src_crs = QgsCoordinateReferenceSystem("EPSG:4326")
            self.dest_crs = self.prj.crs()
            self.transformation = QgsCoordinateTransform(self.src_crs, self.dest_crs, self.prj)
            self.marker = None
            #gps
            self.gpsCon = None
            self.port ="COM5"
            self.gpsDetector = QgsGpsDetector(self.port)
            self.gpsDetector.detected[QgsGpsConnection].connect(self.connection_succeed)
            self.gpsDetector.detectionFailed.connect(self.connection_failed)
            self.gpsDetector.advance()
        except Exception as e:
            print(e)    

    def deactivate(self):
        try:
            print ('GPS deactivated')
            if self.gpsCon is not None:
                self.gpsCon.close()
            if self.canvas is not None:
                self.canvas.scene().removeItem(self.marker)
            self.gps_active = False
        except Exception as e:
            print(e)

    def connection_succeed(self, connection):
        try:
            print("GPS connected")
            self.gps_active = True
            self.gpsCon = connection
            self.gpsCon.stateChanged.connect(self.status_changed)
            #marker
            self.marker = QgsVertexMarker(self.canvas)
            self.marker.setColor(QColor(255, 0, 0))  # (R,G,B)
            self.marker.setIconSize(10)
            self.marker.setIconType(QgsVertexMarker.ICON_CIRCLE)
            self.marker.setPenWidth(3)
        except Exception as e:
            print(e)

    def connection_failed(self):
        if not self.gps_active:
            print('GPS connection failed')

    def status_changed(self,gpsInfo):
        try:
            if self.gpsCon.status() == 3: #data received
                print('fixMode:', gpsInfo.fixMode)
                print('pdop:', gpsInfo.pdop)
                print('satellitesUsed:', gpsInfo.satellitesUsed)
                print('longitude:',gpsInfo.longitude)
                print('latitude',gpsInfo.latitude)
                print('=====')
                wgs84_pointXY = QgsPointXY(gpsInfo.longitude, gpsInfo.latitude)
                wgs84_point = QgsPoint(wgs84_pointXY)
                wgs84_point.transform(self.transformation)
                x = wgs84_point.x()
                y = wgs84_point.y()
                mapPointXY = QgsPointXY(x, y)
                if gpsInfo.pdop >= 1:  # gps ok
                    self.marker.setColor(QColor(0, 200, 0))
                else:
                    self.marker.setColor(QColor(255, 0, 0))            
                self.marker.setCenter(mapPointXY)
                self.marker.show()
                self.canvas.setCenter(mapPointXY)
        except Exception as e:
            print(e)


tool=GPS(iface)
iface.mapCanvas().setMapTool(tool)

Answered by The Rabbit on November 19, 2021

Abstract classes can be used only as a base class of other classes. There are three classes inherited from QgsGpsConnection. See the class diagram in the docs: enter image description here

So try to instantiate a QgsNmeaConnection or QgsGpsdConnection or QgsQtLocationConnection.

Answered by Zoltan on November 19, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP