QGeoPositionInfoSource erzeugt keine Events für positionUpdated mit gpsd (ubuntu)

Alles rund um die Programmierung mit Qt
Antworten
Ritchie
Beiträge: 86
Registriert: 29. Januar 2007 19:41

QGeoPositionInfoSource erzeugt keine Events für positionUpdated mit gpsd (ubuntu)

Beitrag von Ritchie »

Hallo Zusammen,

ich bin gerade dabei ein Programm zum Auslesen einer GPS Maus zu schreiben.
Das entsprechende Plugin "qtposition_gpsd-master" arbeitet korrekt, da die Demoprogramme
"satelliteinfo" und "weatherinfo" korrekt arbeiten. Die Anbindung an den gpsd - dämon arbeitet also.

Leider wird keine von den Slots, welche ich dem Objekt zugeordnet habe, aufgerufen. Ich weiss leider nicht wieso.

Hier meine Defines der Slots

Code: Alles auswählen

class SensorThread : public QThread
{
	Q_OBJECT
...
private slots:
        void    positionUpdated(QGeoPositionInfo);
        void    positionError(QGeoPositionInfoSource::Error);
        void    updateTimeout(void);
....
}
Hier der Beginn der Threads, welcher die Daten auslesen soll:

Code: Alles auswählen

void SensorThread::run(void)
{
SensorValueData     SensorValue;                                        // Query Buffer Element
QDateTime			DateTimeInfo;										// Time buffer value
int16_t             i;

    m_ProgramInfo->writelog(tr("carclient"),tr("SensorThread"),tr("Info"),tr("Thread startup"));

    qt_Position = QGeoPositionInfoSource::createDefaultSource(this);

    if (qt_Position)
        {
        connect(qt_Position, SIGNAL(positionUpdated(QGeoPositionInfo)),this, SLOT(positionUpdated(QGeoPositionInfo)));
        connect(qt_Position, SIGNAL(error(QGeoPositionInfoSource::Error)),this, SLOT(positionError(QGeoPositionInfoSource::Error)));
        connect(qt_Position, SIGNAL(updateTimeout()),this, SLOT(updateTimeout()));

        qt_Position->setUpdateInterval(500);
        qt_Position->setPreferredPositioningMethods(QGeoPositionInfoSource::SatellitePositioningMethods);
        qt_Position->startUpdates();
        }
    else
        m_ProgramInfo->writelog(tr("carclient"),tr("SensorThread"),tr("Error"),tr("Could not create qt_Position Object"));
Hier die einzelen Routinen für die Slots. Derzeit nur mit Testfunktionen um die Anbindung an das Signal zu prüfen.

Code: Alles auswählen

void		SensorThread::positionUpdated(QGeoPositionInfo info)
{
        m_PositionInfo=info;
}
void    SensorThread::positionError(QGeoPositionInfoSource::Error   gpserror)
{
    qDebug() << gpserror;
}
void    SensorThread::updateTimeout(void)
{
    qDebug() << "Time out";
}
Keine der Slots wird aufgerufen und ich weiss wirklich nicht warum.

Hier noch der Log der Applikationsausgabe:
&"warning: GDB: Failed to set controlling terminal: Unpassender IOCTL (I/O-Control) f\303\274r das Ger\303\244t\n"
QObject: Cannot create children for a parent that is in a different thread.
(Parent is SensorThread(0x5555558f42f0), parent's thread is QThread(0x5555557b6f30), current thread is SensorThread(0x5555558f42f0)
Connected to gpsd
Created slave QBuffer(0x7fffd4005540)
Unpausing slave QBuffer(0x7fffd4005540)
Starting gpsd
Debugging has finished
Über diesen Eintrag bin ich noch nicht ganz Schlau geworden.
QObject: Cannot create children for a parent that is in a different thread.
(Parent is SensorThread(0x5555558f42f0), parent's thread is QThread(0x5555557b6f30), current thread is SensorThread(0x5555558f42f0)
Es scheint sich wohl die Art des Starten von Threads geändert haben. Habe eine lange Pause in QT gemacht.

Hat jemand eine Idee, was ich hier falsch gemacht habe ?
Viele Grüße
R.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: QGeoPositionInfoSource erzeugt keine Events für positionUpdated mit gpsd (ubuntu)

Beitrag von Christian81 »

Hallo,
QObject: Cannot create children for a parent that is in a different thread.
Du erzeugst ein Objekt (in diesem Fall innerhalb QGeoPositionInfoSource::createDefaultSource()) mit einen parent. Dieser parent wurde aber in einem anderen Thread erzeugt was nicht erlaubt ist. Dies liegt daran, dass das SensorThread - Objekt im Hauptthread erzeugt wurde, die Funktion SensorThread::run() aber in einem anderen Thread läuft. Siehe QThread-Doku.

Und das andere Problem wird sein, dass die run() - Methode beendet wird (sieht man nicht aber ich gehe mal davon aus, dass Du dort keine Eventloop startest). Deshalb wird der Thread auch beendet und es funktioniert nichts.

Warum das Ganze in einem separaten Thread ausgelagert werden soll wo die Daten sowieso asynchron verarbeitet werden und man augenscheinlich mit Threads noch nichts am Hut hatte sei mal dahingestellt :)
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Ritchie
Beiträge: 86
Registriert: 29. Januar 2007 19:41

Re: QGeoPositionInfoSource erzeugt keine Events für positionUpdated mit gpsd (ubuntu)

Beitrag von Ritchie »

Hallo
Und das andere Problem wird sein, dass die run() - Methode beendet wird (sieht man nicht aber ich gehe mal davon aus, dass Du dort keine Eventloop startest). Deshalb wird der Thread auch beendet und es funktioniert nichts.
Der Thread läuft ohne Problem. Hier werden von verschiedenen Sensorquellen ein Datenbankeintrag erzeugt.
Ich hatte den GPS Sensor vorher per serielle Schnittstelle selber eingelesen, ist mir aber nicht so schön, da dann
andere Programme den GPS Sensor nicht auslesen können. Via "gpsd" ist da besser.
Du erzeugst ein Objekt (in diesem Fall innerhalb QGeoPositionInfoSource::createDefaultSource()) mit einen parent. Dieser parent wurde aber in einem anderen Thread erzeugt was nicht erlaubt ist. Dies liegt daran, dass das SensorThread - Objekt im Hauptthread erzeugt wurde, die Funktion SensorThread::run() aber in einem anderen Thread läuft. Siehe QThread-Doku.
Schaue ich mit an. Habe wohl gelesen das man das jetzt mit signals/slots macht.

Vielen Dank
R.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: QGeoPositionInfoSource erzeugt keine Events für positionUpdated mit gpsd (ubuntu)

Beitrag von Christian81 »

Der Thread läuft ohne Problem.
Wenn keine Eventloop, dann auch keine Signals/Slots... ich glaube immer noch nicht dass der Thread läuft (im Codeschnipsel hört die run-Methode einfach auf)
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Ritchie
Beiträge: 86
Registriert: 29. Januar 2007 19:41

Re: QGeoPositionInfoSource erzeugt keine Events für positionUpdated mit gpsd (ubuntu)

Beitrag von Ritchie »

Hallo Zusammen,

ich habe meine Threads umgebaut und die Meldung "QObject: Cannot create children for a parent that is in a different thread."
Kommt jetzt nicht mehr.

Code: Alles auswählen

...
    QThread* Data_thread = new QThread;
    m_DataThread = new DataThread(&m_ProgramisRunning,SensorBuffer,DebugDiagnosis);	// Create a thread for reading the unit datablocks
    m_DataThread->moveToThread(Data_thread);
    QObject::connect(Data_thread, SIGNAL (started()), m_DataThread, SLOT (run()));

    QThread* Sensor_thread = new QThread;
    m_SensorThread = new SensorThread(&m_ProgramisRunning,SensorBuffer,DebugDiagnosis);	// Create a thread for reading the unit datablocks
    m_SensorThread->moveToThread(Sensor_thread);
    QObject::connect(Sensor_thread, SIGNAL (started()), m_SensorThread, SLOT (run()));

    Data_thread->start();                                  // Start the background tasks
    Sensor_thread->start();
...

Hier mal die ganze Routine

Code: Alles auswählen

void SensorThread::run(void)
{
SensorValueData     SensorValue;                                        // Query Buffer Element
QDateTime			DateTimeInfo;										// Time buffer value
int16_t             i;

    m_ProgramInfo->writelog(tr("carclient"),tr("SensorThread"),tr("Info"),tr("Thread startup"));

    qt_Position = QGeoPositionInfoSource::createDefaultSource(this);

    if (qt_Position)
        {
        connect(qt_Position, SIGNAL(positionUpdated(QGeoPositionInfo)),this, SLOT(positionUpdated(QGeoPositionInfo)));
        connect(qt_Position, SIGNAL(error(QGeoPositionInfoSource::Error)),this, SLOT(positionError(QGeoPositionInfoSource::Error)));
        connect(qt_Position, SIGNAL(updateTimeout()),this, SLOT(updateTimeout()));

        qt_Position->setUpdateInterval(1000);
        qt_Position->setPreferredPositioningMethods(QGeoPositionInfoSource::SatellitePositioningMethods);
        qt_Position->startUpdates();
        }
    else
        m_ProgramInfo->writelog(tr("carclient"),tr("SensorThread"),tr("Error"),tr("Could not create qt_Position Object"));

   m_OBD2Info = new OBD2Serial;

   QThread::msleep(4000);														// Wait a little bit

	while( *m_ProgramIsRunning == true )								// wait until program is close down
		{
        QThread::msleep(1000);													// Update of the message around 100 ms
        if( m_SensorQueryBuffer->locked() == false )
           {
            if (m_SensorQueryBuffer->Size() < 100 )
                {
                qDebug() << "Latitude : " << m_PositionInfo.coordinate().latitude();
                qDebug() << "Longitude: " << m_PositionInfo.coordinate().longitude();


                m_OBD2Info->readRegisters();
                SensorValue.setCustomerID(m_CustomerID);                                // Set the customer
                DateTimeInfo=QDateTime::currentDateTime();
                SensorValue.setValueDateTime(DateTimeInfo);                             // get the actual time
                SensorValue.setAltitude(m_PositionInfo.coordinate().altitude());
                SensorValue.setLatitude(m_PositionInfo.coordinate().latitude());
                SensorValue.setLongitude(m_PositionInfo.coordinate().longitude());
                SensorValue.setSpeed(m_PositionInfo.GroundSpeed);

                for(i=0;i<MAX_OBDINDEX;i++)
                    {
                    SensorValue.setValue(i,m_OBD2Info->getValue(i));      // get all the values of OBD
                    }
                m_SensorQueryBuffer->add(SensorValue);
                }
            else
                {
                m_ProgramInfo->writelog(QObject::tr("carclient"),QObject::tr("SensorThread"),QObject::tr("Warning"),QObject::tr("Buffer full"));
                QThread::msleep(5000);
                }
           }
        else
            {
            QThread::msleep(2000);
            }
        }
    qt_Position->stopUpdates();
    delete m_OBD2Info;
    emit    finished();
}
Leider werden die Event immer noch nicht abgeschossen.

Hier nochmals die Ausgabe der Anwendung.
&"warning: GDB: Failed to set controlling terminal: Unpassender IOCTL (I/O-Control) f\303\274r das Ger\303\244t\n"
QML debugging is enabled. Only use this in a safe environment.
QML Debugger: Waiting for connection on port 39505...
Connected to gpsd
Created slave QBuffer(0x7fffc80060b0)
Unpausing slave QBuffer(0x7fffc80060b0)
Starting gpsd
Latitude : nan
Longitude: nan
QBasicTimer::stop: Failed. Possibly trying to stop from a different thread
Pausing slave QBuffer(0x7fffc80060b0)
Stopping gpsd
Destroyed slave QBuffer(0x7fffc80060b0)
Disconnecting from gpsd
QBasicTimer::stop: Failed. Possibly trying to stop from a different thread
In der Debugger Console taucht das hier auf:
QBasicTimer::stop: Failed. Possibly trying to stop from a different thread
Irgendeine Idee was ich jetzt falsch gemacht habe ?
Ist evtl. meine Methode des Threads Starten falsch ?

Viele Grüße
R.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: QGeoPositionInfoSource erzeugt keine Events für positionUpdated mit gpsd (ubuntu)

Beitrag von Christian81 »

Irgendwo wird wohl noch ein QTimer in einem anderen Thread angelegt als er dann später gestoppt wird. Sieht man hier aber nicht da nur Teile des Codes vorhanden sind.
Und die Idee mit m_ProgramisRunning und der ungeschützte Zugriff auf m_ProgramInfo (was ggf. sogar noch GUI-Aktionen erzeugt) zeigt mir wieder, dass Thread-Programmierung definitiv nicht sinnvoll und mehr Probleme macht als hier zu lösen sind. Versuch es einfach ohne Threads oder fang damit an dich wirklich intensiv mit Threads (Locking, concurrent access, ...) und auch die Qt-Eigenheiten des Hauptthreads zu beschäftigen.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Ritchie
Beiträge: 86
Registriert: 29. Januar 2007 19:41

Re: QGeoPositionInfoSource erzeugt keine Events für positionUpdated mit gpsd (ubuntu)

Beitrag von Ritchie »

Hallo,

der Qtimer wird wohl im Plugin "gpsd" verwendet. Das muss ich mal anschauen.

https://github.com/jmechnich/qtposition_gpsd

Code: Alles auswählen

QGeoSatelliteInfoSourceGpsd::QGeoSatelliteInfoSourceGpsd(QObject* parent)
        : QGeoSatelliteInfoSource(parent)
        , _device(0)
        , _lastError(QGeoSatelliteInfoSource::NoError)
        , _running(false)
        , _wasRunning(false)
        , _reqDone(0)
        , _reqTimer(new QTimer(this))
{
  _reqTimer->setSingleShot(true);
  connect(_reqTimer,SIGNAL(timeout()),this, SLOT(reqTimerTimeout()));
}
Klar ist,das Threads schwieriger sind, inbesondere bei QT, wo ich die Realisierungen
der einzelnen Klassen nicht kenne.

Ich schaue mal, was ich mit Signal und Slots vereinfachen kann. Hätte auch den
Reiz, das es weniger CPU Zeit kostet.

Viele Grüße
R.
Antworten