Модуль Python GPS: чтение последних данных GPS - PullRequest
9 голосов
/ 27 мая 2011

Я пытался работать со стандартным GPS (gps.py) модулем в python 2.6. Предполагается, что он действует как клиент и читает данные GPS с gpsd, работающего в Ubuntu.

В соответствии с документацией на веб-странице GPSD по дизайну клиента ( GPSD Client Howto ), я должен иметь возможность использовать следующий код (слегка измененный из примера) для получения последних значений GPS (широта что меня в основном интересует)

from gps import *
session = gps() # assuming gpsd running with default options on port 2947
session.stream(WATCH_ENABLE|WATCH_NEWSTYLE)
report = session.next()
print report

Если я несколько раз использую next (), он выдаст мне буферизованные значения из нижней части очереди (с момента начала сеанса), а не из показаний ПОСЛЕДНЕГО GPS. Есть ли способ получить более свежие значения с помощью этой библиотеки? В каком-то смысле искать поток до последних значений?

Кто-нибудь получил пример кода, использующего эту библиотеку для опроса gps и получения значения, которое я ищу?

Вот что я пытаюсь сделать:

  1. начать сеанс
  2. Подождите, пока пользователь вызовет метод gps_poll () в моем коде
  3. Внутри этого метода прочитайте последний отчет TPV (Time Position Velocity) и верните широту и долготу
  4. Вернитесь к ожиданию, когда пользователь вызовет gps_poll ()

Ответы [ 3 ]

16 голосов
/ 27 мая 2011

Что вам нужно сделать, это регулярно опрашивать 'session.next ()' - проблема здесь в том, что вы имеете дело с последовательным интерфейсом - вы получаете результаты в порядке их получения. Вы должны поддерживать 'current_value' с последним найденным значением.

Если вы не опросите объект сеанса, в конечном итоге ваш UART FIFO заполнится, и вы все равно не получите никаких новых значений.

Рассмотрите возможность использования потока для этого, не ждите, пока пользователь вызовет gps_poll (), вы должны выполнить опрос, и когда пользователь хочет новое значение, он использует 'get_current_value ()', который возвращает current_value.

С моей головы это может быть что-то простое:

import threading
import time
from gps import *

class GpsPoller(threading.Thread):

   def __init__(self):
       threading.Thread.__init__(self)
       self.session = gps(mode=WATCH_ENABLE)
       self.current_value = None

   def get_current_value(self):
       return self.current_value

   def run(self):
       try:
            while True:
                self.current_value = self.session.next()
                time.sleep(0.2) # tune this, you might not get values that quickly
       except StopIteration:
            pass

if __name__ == '__main__':

   gpsp = GpsPoller()
   gpsp.start()
   # gpsp now polls every .2 seconds for new data, storing it in self.current_value
   while 1:
       # In the main thread, every 5 seconds print the current value
       time.sleep(5)
       print gpsp.get_current_value() 
5 голосов
/ 03 марта 2018

Приведенные выше ответы очень неэффективны и чрезмерно сложны для всех, кто использует современные версии gpsd и нуждается в данных только в определенное время вместо потоковой передачи.

Большинство GPS отправляют информацию о своем положении по крайней мере один раз в секунду.Предположительно, поскольку многие приложения на базе GPS нуждаются в обновлениях в реальном времени, подавляющее большинство примеров клиентов gpsd, которые я видел, используют вышеописанный метод наблюдения потока от gpsd и получения обновлений в реальном времени (более или менее часто, как их отправляет gps).

Однако, если (как в случае с OP) вам не требуется потоковая информация, а просто нужна последняя сообщенная позиция всякий раз, когда она запрашивается (т. Е. Посредством взаимодействия с пользователем или какого-либо другого события).), есть гораздо более эффективный и простой метод: пусть gpsd кеширует последнюю информацию о местоположении и запрашивает ее при необходимости.

* * * * * * Протокол JSON gpsd имеет запрос ?POLL;, который возвращаетсамая свежая информация GPS, которую видел gpsd.Вместо того, чтобы перебирать бэклог сообщений gps и постоянно читать новые сообщения, чтобы избежать полных буферов, вы можете отправить сообщение ?WATCH={"enable":true} в начале сеанса gpsd, а затем запрашивать последнюю информацию о местоположении всякий раз, когда вам это нужно, с помощью?POLL;.Ответ представляет собой один объект JSON, содержащий самую свежую информацию, которую gpsd видел с GPS.

Если вы используете Python3, самый простой способ, который я нашел, это использовать gpsd-py3 пакет доступен на pypi.Чтобы подключиться к gpsd, получить последнюю информацию о местоположении и распечатать текущую позицию:

import gpsd
gpsd.connect()
packet = gpsd.get_current()
print(packet.position())

Вы можете повторить вызов gpsd.get_current() всякий раз, когда вы хотите получить информацию о новой позиции, и за кадром будет выполнен пакет gpsd.?POLL; вызов gpsd и возврат объекта, представляющего ответ.

Делать это со встроенным модулем gps не очень просто, но есть ряд других доступных клиентов Python, иэто также довольно тривиально, чтобы сделать что-нибудь, что может выполнить сокетную связь, включая этот пример, используя telnet:

$ telnet localhost 2947
Trying ::1...
Connected to localhost.
Escape character is '^]'.
{"class":"VERSION","release":"3.16","rev":"3.16","proto_major":3,"proto_minor":11}
?WATCH={"enable":true}
{"class":"DEVICES","devices":[{"class":"DEVICE","path":"/dev/pts/10","driver":"SiRF","activated":"2018-03-02T21:14:52.687Z","flags":1,"native":1,"bps":4800,"parity":"N","stopbits":1,"cycle":1.00}]}
{"class":"WATCH","enable":true,"json":false,"nmea":false,"raw":0,"scaled":false,"timing":false,"split24":false,"pps":false}
?POLL;
{"class":"POLL","time":"2018-03-02T21:14:54.873Z","active":1,"tpv":[{"class":"TPV","device":"/dev/pts/10","mode":3,"time":"2005-06-09T14:34:53.280Z","ept":0.005,"lat":46.498332203,"lon":7.567403907,"alt":1343.165,"epx":24.829,"epy":25.326,"epv":78.615,"track":10.3788,"speed":0.091,"climb":-0.085,"eps":50.65,"epc":157.23}],"gst":[{"class":"GST","device":"/dev/pts/10","time":"1970-01-01T00:00:00.000Z","rms":0.000,"major":0.000,"minor":0.000,"orient":0.000,"lat":0.000,"lon":0.000,"alt":0.000}],"sky":[{"class":"SKY","device":"/dev/pts/10","time":"2005-06-09T14:34:53.280Z","xdop":1.66,"ydop":1.69,"vdop":3.42,"tdop":3.05,"hdop":2.40,"gdop":5.15,"pdop":4.16,"satellites":[{"PRN":23,"el":6,"az":84,"ss":0,"used":false},{"PRN":28,"el":7,"az":160,"ss":0,"used":false},{"PRN":8,"el":66,"az":189,"ss":45,"used":true},{"PRN":29,"el":13,"az":273,"ss":0,"used":false},{"PRN":10,"el":51,"az":304,"ss":29,"used":true},{"PRN":4,"el":15,"az":199,"ss":36,"used":true},{"PRN":2,"el":34,"az":241,"ss":41,"used":true},{"PRN":27,"el":71,"az":76,"ss":42,"used":true}]}]}
?POLL;
{"class":"POLL","time":"2018-03-02T21:14:58.856Z","active":1,"tpv":[{"class":"TPV","device":"/dev/pts/10","mode":3,"time":"2005-06-09T14:34:53.280Z","ept":0.005,"lat":46.498332203,"lon":7.567403907,"alt":1343.165,"epx":24.829,"epy":25.326,"epv":78.615,"track":10.3788,"speed":0.091,"climb":-0.085,"eps":50.65,"epc":157.23}],"gst":[{"class":"GST","device":"/dev/pts/10","time":"1970-01-01T00:00:00.000Z","rms":0.000,"major":0.000,"minor":0.000,"orient":0.000,"lat":0.000,"lon":0.000,"alt":0.000}],"sky":[{"class":"SKY","device":"/dev/pts/10","time":"2005-06-09T14:34:53.280Z","xdop":1.66,"ydop":1.69,"vdop":3.42,"tdop":3.05,"hdop":2.40,"gdop":5.15,"pdop":4.16,"satellites":[{"PRN":23,"el":6,"az":84,"ss":0,"used":false},{"PRN":28,"el":7,"az":160,"ss":0,"used":false},{"PRN":8,"el":66,"az":189,"ss":45,"used":true},{"PRN":29,"el":13,"az":273,"ss":0,"used":false},{"PRN":10,"el":51,"az":304,"ss":29,"used":true},{"PRN":4,"el":15,"az":199,"ss":36,"used":true},{"PRN":2,"el":34,"az":241,"ss":41,"used":true},{"PRN":27,"el":71,"az":76,"ss":42,"used":true}]}]}
2 голосов
/ 18 марта 2016

Добавление двух моих центов.

По какой-то причине мой малиновый пи продолжит выполнение потока, и мне придется жестко сбросить пи.

Итак, я объединил sysnthesizerpatel и ответ, который нашел в блоге Дэна Манделя здесь .

Мой класс gps_poller выглядит следующим образом:

import os 
from gps import *
from time import *
import time 
import threading 

class GpsPoller(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.session = gps(mode=WATCH_ENABLE)
        self.current_value = None 
        self.running = True 

    def get_current_value(self):
        return self.current_value

    def run(self):
        try:
            while self.running:
                self.current_value = self.session.next() 
        except StopIteration:
            pass

И используемый код выглядит следующим образом:

from gps_poll import *

if __name__ == '__main__':
    gpsp = GpsPoller()
    try: 
        gpsp.start() 
        while True:
            os.system('clear')
            report = gpsp.get_current_value()
            # print report 
            try: 
                if report.keys()[0] == 'epx':
                    print report['lat']
                    print report['lon']           
                time.sleep(.5)
            except(AttributeError, KeyError):
                pass 
            time.sleep(0.5)

    except(KeyboardInterrupt, SystemExit):
        print "\nKilling Thread.."
        gpsp.running = False 
        gpsp.join()

    print "Done.\nExiting." 

Код также можно найти здесь: Здесь и Здесь

...