Python GPS Module: Reading latest GPS Data

后端 未结 3 1309
不思量自难忘°
不思量自难忘° 2020-12-13 22:39

I have been trying to work with the standard GPS (gps.py) module in python 2.6. This is supposed to act as a client and read GPS Data from gpsd running in U

相关标签:
3条回答
  • 2020-12-13 22:59

    Adding my two cents.

    For whatever reason my raspberry pi would continue to execute a thread and I'd have to hard reset the pi.

    So I've combined sysnthesizerpatel and an answer I found on Dan Mandel's blog here.

    My gps_poller class looks like this:

    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
    

    And the code in use looks like this:

    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." 
    

    You can also find the code here: Here and Here

    0 讨论(0)
  • 2020-12-13 23:07

    The above answers are very inefficient and overly complex for anyone using modern versions of gpsd and needing data at only specific times, instead of streaming.

    Most GPSes send their position information at least once per second. Presumably since many GPS-based applications desire real-time updates, the vast majority of gpsd client examples I've seen use the above method of watching a stream from gpsd and receiving realtime updates (more or less as often as the gps sends them).

    However, if (as in the OP's case) you don't need streaming information but just need the last-reported position whenever it's requested (i.e. via user interaction or some other event), there's a much more efficient and simpler method: let gpsd cache the latest position information, and query it when needed.

    The gpsd JSON protocol has a ?POLL; request, which returns the most recent GPS information that gpsd has seen. Instead of having to iterate over the backlog of gps messages, and continually read new messages to avoid full buffers, you can send a ?WATCH={"enable":true} message at the start of the gpsd session, and then query the latest position information whenever you need it with ?POLL;. The response is a single JSON object containing the most recent information that gpsd has seen from the GPS.

    If you're using Python3, the easiest way I've found is to use the gpsd-py3 package available on pypi. To connect to gpsd, get the latest position information, and print the current position:

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

    You can repeat the gpsd.get_current() call whenever you want new position information, and behind the scenes the gpsd package will execute the ?POLL; call to gpsd and return an object representing the response.

    Doing this with the built-in gps module isn't terribly straightforward, but there are a number of other Python clients available, and it's also rather trivial to do with anything that can perform socket communication, including this example using 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}]}]}
    
    0 讨论(0)
  • 2020-12-13 23:13

    What you need to do is regularly poll 'session.next()' - the issue here is that you're dealing with a serial interface - you get results in the order they were received. Its up to you to maintain a 'current_value' that has the latest retrieved value.

    If you don't poll the session object, eventually your UART FIFO will fill up and you won't get any new values anyway.

    Consider using a thread for this, don't wait for the user to call gps_poll(), you should be polling and when the user wants a new value they use 'get_current_value()' which returns current_value.

    Off the top of my head it could be something as simple as this:

    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() 
    
    0 讨论(0)
提交回复
热议问题