Beispiel #1
0
    def __init__(self, observers=None):
        super(GpxParser, self).__init__()

        self.log = LogWriter()

        self.track = None

        # The trackpoint we will build up
        self.tp = None
        self.tp_cb = None

        self.location = []
        self.attrs = None

        self.content = None

        self.fout = sys.stdout

        if observers:
            try:
                # Ensure observers is iterable
                iter(observers)
                self.observers = observers
            except TypeError:
                # Not iterable
                self.observers = [observers]
        else:
            self.observers = [GpxObserverPrint(self.log)]
Beispiel #2
0
    def __init__(self, qtree, max_match_threshold_metres, outputFormatter, poiFetcher=None):

        # TODO beware multiple instances will overwrite each other. consider tempfile.mktemp. This is only for debugging anyway
        self.gpxLongStop = gpxWriter(open(gps.lib.gpxUtil.tempFilePath("stop_unknown.GPX", "gpx2txt"), "w"))

        if not self.gpxLongStop:
            raise Exception("Failed create long stop gpx file" + gps.lib.gpxUtil.tempFilePath("stop_unknown.GPX", "gpx2txt"))

        self.segmentsCompare = qtree

        self.poi = poiFetcher or gps.lib.petitpois.FetchPoi(True)

        self.max_match_threshold_metres = max_match_threshold_metres
        self.output = outputFormatter

        self.log = LogWriter()

        self.fetchPois = True
Beispiel #3
0
class gpxTrackPointDistances(GpxObserver):

    """
    For debugging..
    Print the distance between successive points for
    a real track and an interpolated track
    """

    def __init__(self, lower, upper):
        super(gpxTrackPointDistances, self).__init__()
        self.upper = upper
        self.lower = lower
        self.log = LogWriter()

    def nextTrack(self, track):

        self.log.o("TRACK: %s" % track.name)

        # Real points
        last = None
        d = 0
        for point in track.points():
            if last:
                d = point.distance(last)

            self.log.o("dist real=%g" % d)
            last = point

        # Virtual points (interpolated)
        last = None
        d = 0
        for point in track.points_virtual(self.lower, self.upper):
            if last:
                d = point.distance(last)

            self.log.o("[%s] dist virt=%g" % (point.type, d))
            last = point
Beispiel #4
0
class TrackCompareObserver(GpxObserver):

    def __init__(self, qtree, max_match_threshold_metres, outputFormatter, poiFetcher=None):

        # TODO beware multiple instances will overwrite each other. consider tempfile.mktemp. This is only for debugging anyway
        self.gpxLongStop = gpxWriter(open(gps.lib.gpxUtil.tempFilePath("stop_unknown.GPX", "gpx2txt"), "w"))

        if not self.gpxLongStop:
            raise Exception("Failed create long stop gpx file" + gps.lib.gpxUtil.tempFilePath("stop_unknown.GPX", "gpx2txt"))

        self.segmentsCompare = qtree

        self.poi = poiFetcher or gps.lib.petitpois.FetchPoi(True)

        self.max_match_threshold_metres = max_match_threshold_metres
        self.output = outputFormatter

        self.log = LogWriter()

        self.fetchPois = True

    def start(self):
        ## TODO doesn't this get called anyway?
        self.output.start()

    def end(self):
        self.output.end()

    def haveBounds(self, bounds):
        pass

    def nextTrack(self, track):
        super(TrackCompareObserver, self).nextTrack(track)

        matcher = gpx2txtMatcher(track, self.output, self.max_match_threshold_metres)

        matcher.gpxLongStop = self.gpxLongStop

        if self.fetchPois:

            self.log.dbg("Track: %s" % (track.filename()))

            self.log.dbg("Fetching POI")

            tb = track.getBounds()
            self.log.i("Track bounds are: %s" % tb)

            self.log.i("Track bounded area is: %s (%s)" % (gps.lib.gpxUtil.area(tb),
                                                           gps.lib.gpxUtil.width_height(tb)))

            area = tb.area() / 1000 / 1000

            # Don't get crazy large areas
            if not area < 5000:
                log.i("Skipping fetching web waypoints as area is very large")
            else:

                bltr = tb.BLTR()

                # Note we are creating another WayPointGatherer, but this one is filtered
                # We will share the same qtree as the original one
                wpgFiltered = WayPointGathererFiltered(self.segmentsCompare)

                #  going to split the boundaries in the smaller chunks
                for poi in self.poi.fetchPoi_gpx_split(*bltr):
                    # TODO maybe move out "hit" pubs to our file (especially when have stopped there)
                    # self.log.i("Wrote poi for track to %s" % (poi))

                    # Let's be quite precise to include these ones.  If any of these points are near points
                    # we already have loaded then they will be rejected.  Otherwise we get duplicates listed.
                    dthres = 30

                    wpgFiltered.Parse(poi, dthres)

        #         self.log.o("TRACK: %s|%s, %s - %s" % (track.filename(), track.name, track.time_first, track.time_last))

        # TODO should interpolate the track such that we only get a point every 100 metres
        # or so to limit number of checks we do
        # Compare with the db

        self.output.startTrack(track)

        # This calls back to "foundPoint" in the derived matcher class above
        hitStats = matcher.matchAlgo2(track, self.segmentsCompare)

        matcher.endTrack()

        hitStatsX = {}
        hitStatsX["hit"] = hitStats[0]
        hitStatsX["miss"] = hitStats[1]
        hitStatsX["match_pct"] = hitStats[2]
        hitStatsX["stopTimeTotal"] = matcher.stopSpotter.stopTimeTotal()
        hitStatsX["stops"] = len(matcher.stopSpotter.stops)
        hitStatsX["distance"] = track.distance

        hitStatsX["st_pct"] = hitStatsX["mv_pct"] = hitStatsX["movingTime"] = 0
        ts = track.duration()
        if ts:
            hitStatsX["st_pct"] = (hitStatsX["stopTimeTotal"] / ts) * 100
            hitStatsX["mv_pct"] = 100 - hitStatsX["st_pct"]
            hitStatsX["movingTime"] = ts - hitStatsX["stopTimeTotal"] # format with gpxUtil.duration()



        self.output.endTrack(hitStatsX)

    def nextTrackPoint(self, trackPoint):
        pass

    def nextRoutePoint(self, routePoint):
        pass

    def done(self):
        self.gpxLongStop.close()
Beispiel #5
0
    MatchTimeAndMultiLocationsDecorator, \
    MatchLoggerDecorator, \
    MatchSummaryDecorator, \
    MatchAccumulatorDecorator,\
    MatchJsonPrinterDecorator

import gps.lib.gpxUtil

# POI fetcher
import gps.lib.petitpois

from gps.lib.gpxWaypointDB import WaypointDB

###############################################################################

log = LogWriter()

###############################################################################


class gpx2txtMatcher(Matcher):
    """
    This is a subclass of the Matcher class, which is the main class for 
    matching trackpoints to waypoints.
    """

    # The match threshold here determines how extended the select on the waypoints is
    def __init__(self, track, output, match_threshold_metres):
        super(gpx2txtMatcher, self).__init__(output.log, match_threshold_metres)
        
        self.track = track
Beispiel #6
0
 def __init__(self, log=None):
     self.log = log or LogWriter()
Beispiel #7
0
 def __init__(self, lower, upper):
     super(gpxTrackPointDistances, self).__init__()
     self.upper = upper
     self.lower = lower
     self.log = LogWriter()
Beispiel #8
0
#!/usr/bin/env python

from __future__ import print_function

import sys
import os

from gps.lib.gpsObserver import GpxObserver
from gps.lib.formats.GpxParser import GpxParser
from gps.lib.gpxQTree import SegmentsQTree
from gps.lib.primitives.gpxBounds import Bounds
from gps.lib.primitives.points import Point
from gps.lib.logWriter import LogWriter
from gpxWaypointDB import WaypointDB

log = LogWriter()


class WayPointGatherer(GpxObserver):
    """
    As waypoints are found parsing the gpx files, add them to an internal qtree
    """

    def __init__(self):
        super(WayPointGatherer, self).__init__()

        # Note if we used smaller bounds we would automatically exclude points for countries miles away
        # TODO OPT read the tracks first, work out the (extended) bounds and use for these bounds   
        bounds = Bounds()
        bounds.registerPoint(Point(-90, -90))
        bounds.registerPoint(Point(90, 90))
Beispiel #9
0
class GpxParser(ContentHandler, object):
    """
    Parse a gpx file, and either call a callback for each tp parsed
    (if cb supplied) or just works out some stats on the tps read.
    
    Note that ContentHandler is an old style class, hence why we also
    inherit from object to allow compatibility with new style classes.
    """

    #def characters(self, ch):
    #sys.stdout.write(ch.encode("Latin-1"))

    # observers should "implement" GpxObserver
    def __init__(self, observers=None):
        super(GpxParser, self).__init__()

        self.log = LogWriter()

        self.track = None

        # The trackpoint we will build up
        self.tp = None
        self.tp_cb = None

        self.location = []
        self.attrs = None

        self.content = None

        self.fout = sys.stdout

        if observers:
            try:
                # Ensure observers is iterable
                iter(observers)
                self.observers = observers
            except TypeError:
                # Not iterable
                self.observers = [observers]
        else:
            self.observers = [GpxObserverPrint(self.log)]

    def run(self, filenames):
        self.Parse(filenames)

    def startElement(self, name, attrs):

        self.location.append(name)
        self.attrs = attrs
        #print("At", self.location)

        # See also endElement where much of the action is.

        if self.location == ["gpx", "trk"]:
            self.track = Track()

        elif self.location == ["gpx", "trk", "trkseg"]:
            self.track.startSegment()

        elif self.location == ["gpx", "trk", "trkseg", "trkpt"]:
            self.tp = Trackpoint(attrs.get("lat"), attrs.get("lon"))

        elif self.location == ["gpx", "wpt"]:
            self.wayPoint = WayPoint(attrs.get("lat"), attrs.get("lon"))

        elif self.location == ["gpx", "rte"]:
            self.route = Route()

        elif self.location == ["gpx", "rte", "rtept"]:
            self.rp = RoutePoint(attrs.get("lat"), attrs.get("lon"))
        else:

            pass
            #self.log.i("IGNORING START OF SECTION:%s" % self.location)

        self.content = None

    def characters(self, content):

        if self.content is None:
            #            print("type first assign:", type(content))
            self.content = content
        else:
            #            print("add type to content", type(content))

            # Remember content is not complete!!
            self.content += content

    def selectObj(self):
        obj = None
        if len(self.location) >= 2:

            if self.location[:4] == ["gpx", "trk", "trkseg", "trkpt"]:
                obj = self.tp
            else:
                top_level = self.location[1]
                if top_level == "trk":
                    obj = self.track
                elif top_level == "wpt":
                    obj = self.wayPoint
                elif top_level == "rte":
                    obj = self.route

        return obj

    def endElement(self, name):

        if self.content:
            #            print("have full content of type", type(self.content), self.content)
            content = self.content.strip()
#            content = self.content.strip().encode('ascii', 'ignore')  # this screws up on python3
#            print("have full content ENCODED of type", type(content), content)
        else:
            content = None

        obj = self.selectObj()

        # Handle the content

        if self.location[:2] == ["gpx", "trk"]:
            if self.location == ["gpx", "trk"]:
                [observer.nextTrack(self.track) for observer in self.observers]
                self.track = None

            elif self.location == ["gpx", "trk", "name"]:
                obj.name = content

            elif self.location == ["gpx", "trk", "type"]:
                obj.type = content

            elif self.location == ["gpx", "trk", "trkseg"]:
                [
                    observer.nextTrackSegment(self.track.currentSegment)
                    for observer in self.observers
                ]
                self.track.endSegment()

            elif self.location == ["gpx", "trk", "trkseg", "trkpt"]:
                self.track.addPoint(self.tp)
                [
                    observer.nextTrackPoint(self.tp)
                    for observer in self.observers
                ]
                self.tp = None

            elif self.location == [
                    "gpx", "trk", "trkseg", "trkpt", "extensions",
                    "gpxtpx:TrackPointExtension", "gpxtpx:hr"
            ]:
                self.tp.hr = int(content)

            elif self.location == [
                    "gpx", "trk", "trkseg", "trkpt", "extensions",
                    "gpxtpx:TrackPointExtension", "gpxtpx:cad"
            ]:
                self.tp.cad = int(content)

            elif self.location == ["gpx", "trk", "trkseg", "trkpt", "time"]:

                #                print("yContent is type", type(content))
                #                print("yContent value is", content)

                self.tp.setTime(content)

            elif self.location == ["gpx", "trk", "trkseg", "trkpt", "ele"]:
                if content:
                    #                    print("xContent is type", type(content))
                    #                    print("xContent value is", content)
                    self.tp.elevation = float(content)

        elif self.location[:2] == ['gpx', 'wpt']:

            if self.location == ['gpx', 'wpt']:
                [
                    observer.nextWayPoint(self.wayPoint)
                    for observer in self.observers
                ]
                self.wayPoint = None

            elif self.location == ["gpx", "wpt", "name"]:
                obj.name = content

            elif self.location == ["gpx", "wpt", "cmt"]:
                obj.comment = content
            else:
                pass

        elif self.location[:2] == ['gpx', 'rte']:
            if self.location == ['gpx', 'rte']:
                [observer.nextRoute(self.route) for observer in self.observers]
                self.route = None

            elif self.location == ['gpx', 'rte', 'name']:
                self.route.name = content

            elif self.location == ["gpx", "rte", "rtept"]:
                self.route.addPoint(self.rp)
                [
                    observer.nextRoutePoint(self.rp)
                    for observer in self.observers
                ]

            elif self.location == ["gpx", "rte", "rtept", "sym"]:
                self.rp.sym = content

            elif self.location == ["gpx", "rte", "rtept", "type"]:
                self.rp.type = content

        elif self.location == ['gpx']:
            pass
        elif self.location == ["gpx", "metadata", "bounds"]:
            minlat = self.attrs.getValue("minlat")
            minlon = self.attrs.getValue("minlon")
            maxlat = self.attrs.getValue("maxlat")
            maxlon = self.attrs.getValue("maxlon")

            bounds = Bounds()
            bounds.registerPoint(Point(minlon, minlat))
            bounds.registerPoint(Point(maxlon, maxlat))

            [observer.haveBounds(bounds) for observer in self.observers]

        elif self.location[:2] == ["gpx", "metadata"]:
            #         elif self.location == ["gpx", "metadata", "time"]:
            pass
        else:
            self.log.i("IGNORED: %s, content: %s" % (self.location, content))

        self.content = None

        self.location.pop()

    def endDocument(self):
        pass
        #if self.opts.print_summary:
        #self.track.PrintStats()

    def Parse(self, files):

        if not isinstance(files, (list, tuple)):
            files = [files]

        parser = xml.sax.make_parser()
        parser.setContentHandler(self)

        [observer.start() for observer in self.observers]

        for f in files:

            # Create a new analyzer to each time so values from previous file not used
            # This is the object we will register the trackpoints with
            try:
                [observer.nextFile(f) for observer in self.observers]

                parser.parse(f)

            except IOError as e:

                try:
                    (err_number, strerror) = e.args
                    if err_number == errno.EPIPE:
                        # this happens when piped into head, for example
                        continue
                except:
                    pass

                self.log.i("IOError occurred parsing file")
                self.log.i(e)
                raise e

            #except ValueError, e:
            #    self.log..i("Value Error exception caught:", e

        [observer.end() for observer in self.observers]