class GraphBuilder(object):

    LATITUDE = 0
    LONGITUDE = 1

    def __init__(self, osmfile):
        # parse the input file and save its contents in memory

        # initialize street network
        self.street_network = StreetNetwork()

        # coord pairs as returned from imposm
        self.coords = dict()

        # max and min latitude and longitude
        self.bounds = dict()
        self.bounds["min_lat"] = 9999
        self.bounds["max_lat"] = -9999
        self.bounds["min_lon"] = 9999
        self.bounds["max_lon"] = -9999

        # active copy of OSM data indexed by OSM id
        self.all_osm_relations = dict()
        self.all_osm_ways = dict()
        self.all_osm_nodes = dict()

        # nodes with specific landuse tags
        self.residential_nodes = set()
        self.industrial_nodes = set()
        self.commercial_nodes = set()

        # subset that is also connected to the street network
        self.connected_residential_nodes = set()
        self.connected_industrial_nodes = set()
        self.connected_commercial_nodes = set()

        # mapping from highway types to max speeds
        # we do this so there"s always a speed limit for every edge, even if
        # none is in the OSM data
        self.max_speed_map = dict()
        self.max_speed_map["motorway"] = 140
        self.max_speed_map["trunk"] = 120
        self.max_speed_map["primary"] = 100
        self.max_speed_map["secondary"] = 80
        self.max_speed_map["tertiary"] = 70
        self.max_speed_map["road"] = 50
        self.max_speed_map["minor"] = 50
        self.max_speed_map["unclassified"] = 50
        self.max_speed_map["residential"] = 30
        self.max_speed_map["track"] = 30
        self.max_speed_map["service"] = 20
        self.max_speed_map["path"] = 10
        self.max_speed_map["cycleway"] = 1   # >0 to prevent infinite weights
        self.max_speed_map["bridleway"] = 1  # >0 to prevent infinite weights
        self.max_speed_map["pedestrian"] = 1 # >0 to prevent infinite weights
        self.max_speed_map["footway"] = 1    # >0 to prevent infinite weights

        p = OSMParser(concurrency = 1,
                      coords_callback = self.coords_callback,
                      nodes_callback = self.nodes_callback,
                      ways_callback = self.ways_callback,
                      relations_callback = self.relations_callback)
        p.parse(osmfile)

    def build_street_network(self):
        # add boundaries to street network
        if 9999 not in self.bounds.values() and -9999 not in self.bounds.values():
            self.street_network.set_bounds(self.bounds["min_lat"], self.bounds["max_lat"],
                                           self.bounds["min_lon"], self.bounds["max_lon"])

        # construct the actual graph structure from the input data
        for osmid, tags, refs in self.all_osm_ways.values():
            if "highway" in tags:
                if not self.street_network.has_node(refs[0]):
                    coord = self.coords[refs[0]]
                    self.street_network.add_node(refs[0], coord[self.LONGITUDE], coord[self.LATITUDE])
                for i in range(0, len(refs)-1):
                    if not self.street_network.has_node(refs[i+1]):
                        coord = self.coords[refs[i+1]]
                        self.street_network.add_node(refs[i+1], coord[self.LONGITUDE], coord[self.LATITUDE])

                    street = (refs[i], refs[i+1])

                    # calculate street length
                    length = self.length_haversine(refs[i], refs[i+1])

                    # determine max speed and number of lanes
                    max_speed = 50
                    lanes = 2
                    if tags["highway"] in self.max_speed_map.keys():
                        max_speed = self.max_speed_map[tags["highway"]]
                    if "maxspeed" in tags:
                        max_speed_tag = tags["maxspeed"]
                        if max_speed_tag.isdigit():
                            max_speed = int(max_speed_tag)
                        elif max_speed_tag.endswith("mph"):
                            max_speed = int(max_speed_tag.replace("mph", "").strip(" "))
                        elif max_speed_tag == "none":
                            max_speed = 140
                    elif "lanes" in tags:
                        lanes_tag = tags["lanes"]
                        if lanes_tag.isdigit():
                            lanes = int(lanes_tag)
                        elif lanes_tag == "none":
                            lanes = 2

                    # add street to street network
                    if not self.street_network.has_street(street):
                        self.street_network.add_street(street, length, max_speed,lanes)

        return self.street_network

    def find_node_categories(self):
        # collect relevant categories of nodes in their respective sets
        # TODO there has to be a better way to do this
        # TODO do this inside class StreetNetwork?
        for osmid, tags, members in self.all_osm_relations.values():
            if "landuse" in tags:
                if tags["landuse"] == "residential":
                    self.residential_nodes = self.residential_nodes | self.get_all_child_nodes(osmid)
                if tags["landuse"] == "industrial":
                    self.industrial_nodes = self.industrial_nodes | self.get_all_child_nodes(osmid)
                if tags["landuse"] == "commercial":
                    self.commercial_nodes = self.commercial_nodes | self.get_all_child_nodes(osmid)
        for osmid, tags, refs in self.all_osm_ways.values():
            if "landuse" in tags:
                if tags["landuse"] == "residential":
                    self.residential_nodes = self.residential_nodes | self.get_all_child_nodes(osmid)
                if tags["landuse"] == "industrial":
                    self.industrial_nodes = self.industrial_nodes | self.get_all_child_nodes(osmid)
                if tags["landuse"] == "commercial":
                    self.commercial_nodes = self.commercial_nodes | self.get_all_child_nodes(osmid)
        for osmid, tags, coords in self.all_osm_nodes.values():
            if "landuse" in tags:
                if tags["landuse"] == "residential":
                    self.residential_nodes = self.residential_nodes | self.get_all_child_nodes(osmid)
                if tags["landuse"] == "industrial":
                    self.industrial_nodes = self.industrial_nodes | self.get_all_child_nodes(osmid)
                if tags["landuse"] == "commercial":
                    self.commercial_nodes = self.commercial_nodes | self.get_all_child_nodes(osmid)
        street_network_nodes = set(self.street_network.get_nodes())
        self.connected_residential_nodes = self.residential_nodes & street_network_nodes
        self.connected_industrial_nodes = self.industrial_nodes & street_network_nodes
        self.connected_commercial_nodes = self.commercial_nodes & street_network_nodes

    def coords_callback(self, coords):
        for osmid, lon, lat in coords:
            self.coords[osmid] = dict([(self.LATITUDE, lat), (self.LONGITUDE, lon)])
            self.bounds["min_lat"] = min(self.bounds["min_lat"], lat)
            self.bounds["min_lon"] = min(self.bounds["min_lon"], lon)
            self.bounds["max_lat"] = max(self.bounds["max_lat"], lat)
            self.bounds["max_lon"] = max(self.bounds["max_lon"], lon)

    def nodes_callback(self, nodes):
        for node in nodes:
            self.all_osm_nodes[node[0]] = node

    def ways_callback(self, ways):
        for way in ways:
            self.all_osm_ways[way[0]] = way

    def relations_callback(self, relations):
        for relation in relations:
            self.all_osm_relations[relation[0]] = relation

    def get_all_child_nodes(self, osmid):
        # given any OSM id, construct a set of the ids of all descendant nodes
        if osmid in self.all_osm_nodes.keys():
            return set([osmid])
        if osmid in self.all_osm_relations.keys():
            children = set()
            for osmid, osmtype, role in self.all_osm_relations[osmid][2]:
                children = children | self.get_all_child_nodes(osmid)
            return children
        if osmid in self.all_osm_ways.keys():
            children = set()
            for ref in self.all_osm_ways[osmid][2]:
                children.add(ref)
            return children
        return set()

    def length_euclidean(self, id1, id2):
        # calculate distance on a 2D plane assuming latitude and longitude
        # form a planar uniform coordinate system (obviously not 100% accurate)
        p1 = self.coords[id1]
        p2 = self.coords[id2]
        # assuming distance between to degrees of latitude to be approx.
        # 66.4km as is the case for Hamburg, and distance between two
        # degrees of longitude is always 111.32km
        dist = sqrt( ((p2[self.LATITUDE]-p1[self.LATITUDE])*111.32)**2
                     + ((p2[self.LONGITUDE]-p1[self.LONGITUDE])*66.4)**2 )
        return dist*1000 # return distance in m

    def length_haversine(self, id1, id2):
        # calculate distance using the haversine formula, which incorporates
        # earth curvature
        # see http://en.wikipedia.org/wiki/Haversine_formula
        lat1 = self.coords[id1][self.LATITUDE]
        lon1 = self.coords[id1][self.LONGITUDE]
        lat2 = self.coords[id2][self.LATITUDE]
        lon2 = self.coords[id2][self.LONGITUDE]
        lat1, lon1, lat2, lon2 = map(radians, [lat1, lon1, lat2, lon2])
        dlon = lon2 - lon1
        dlat = lat2 - lat1
        a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
        c = 2 * asin(sqrt(a))
        return 6367000 * c # return distance in m
Beispiel #2
0
                           available_braking_distance * 2)  # m/s
    # cars respect speed limit
    actual_speed = min(max_speed, potential_speed * 3.6)  # km/h

    return actual_speed


if __name__ == "__main__":

    def out(*output):
        for o in output:
            print o,
        print ''

    street_network = StreetNetwork()
    street_network.add_node(1, 0, 0)
    street_network.add_node(2, 0, 0)
    street_network.add_node(3, 0, 0)
    street_network.add_street((
        1,
        2,
    ), 10, 50)
    street_network.add_street((
        2,
        3,
    ), 100, 140)

    trips = dict()
    trips[1] = [3]

    sim = Simulation(street_network, trips, out)
Beispiel #3
0
class GraphBuilder(object):

    LATITUDE = 0
    LONGITUDE = 1

    def __init__(self, osmfile):
        # parse the input file and save its contents in memory

        # initialize street network
        self.street_network = StreetNetwork()

        # coord pairs as returned from imposm
        self.coords = dict()

        # max and min latitude and longitude
        self.bounds = dict()
        self.bounds["min_lat"] = 9999
        self.bounds["max_lat"] = -9999
        self.bounds["min_lon"] = 9999
        self.bounds["max_lon"] = -9999

        # active copy of OSM data indexed by OSM id
        self.all_osm_relations = dict()
        self.all_osm_ways = dict()
        self.all_osm_nodes = dict()

        # nodes with specific landuse tags
        self.residential_nodes = set()
        self.industrial_nodes = set()
        self.commercial_nodes = set()

        # subset that is also connected to the street network
        self.connected_residential_nodes = set()
        self.connected_industrial_nodes = set()
        self.connected_commercial_nodes = set()

        # mapping from highway types to max speeds
        # we do this so there"s always a speed limit for every edge, even if
        # none is in the OSM data
        self.max_speed_map = dict()
        self.max_speed_map["motorway"] = 140
        self.max_speed_map["trunk"] = 120
        self.max_speed_map["primary"] = 100
        self.max_speed_map["secondary"] = 80
        self.max_speed_map["tertiary"] = 70
        self.max_speed_map["road"] = 50
        self.max_speed_map["minor"] = 50
        self.max_speed_map["unclassified"] = 50
        self.max_speed_map["residential"] = 30
        self.max_speed_map["track"] = 30
        self.max_speed_map["service"] = 20
        self.max_speed_map["path"] = 10
        self.max_speed_map["cycleway"] = 1   # >0 to prevent infinite weights
        self.max_speed_map["bridleway"] = 1  # >0 to prevent infinite weights
        self.max_speed_map["pedestrian"] = 1 # >0 to prevent infinite weights
        self.max_speed_map["footway"] = 1    # >0 to prevent infinite weights

        p = OSMParser(concurrency = 1,
                      coords_callback = self.coords_callback,
                      nodes_callback = self.nodes_callback,
                      ways_callback = self.ways_callback,
                      relations_callback = self.relations_callback)
        p.parse(osmfile)

    def build_street_network(self):
        # add boundaries to street network
        if 9999 not in self.bounds.values() and -9999 not in self.bounds.values():
            self.street_network.set_bounds(self.bounds["min_lat"], self.bounds["max_lat"], 
                                           self.bounds["min_lon"], self.bounds["max_lon"])

        # construct the actual graph structure from the input data
        for osmid, tags, refs in self.all_osm_ways.values():
            if "highway" in tags:
                if not self.street_network.has_node(refs[0]):
                    coord = self.coords[refs[0]]
                    self.street_network.add_node(refs[0], coord[self.LONGITUDE], coord[self.LATITUDE])
                for i in range(0, len(refs)-1):
                    if not self.street_network.has_node(refs[i+1]):
                        coord = self.coords[refs[i+1]]
                        self.street_network.add_node(refs[i+1], coord[self.LONGITUDE], coord[self.LATITUDE])

                    street = (refs[i], refs[i+1])

                    # calculate street length
                    length = self.length_haversine(refs[i], refs[i+1])

                    # determine max speed
                    max_speed = 50
                    if tags["highway"] in self.max_speed_map.keys():
                        max_speed = self.max_speed_map[tags["highway"]]
                    if "maxspeed" in tags:
                        max_speed_tag = tags["maxspeed"]
                        if max_speed_tag.isdigit():
                            max_speed = int(max_speed_tag)
                        elif max_speed_tag.endswith("mph"):
                            max_speed = int(max_speed_tag.replace("mph", "").strip(" "))
                        elif max_speed_tag == "none":
                            max_speed = 140

                    # add street to street network
                    if not self.street_network.has_street(street):
                        self.street_network.add_street(street, length, max_speed)

        return self.street_network

    def find_node_categories(self):
        # collect relevant categories of nodes in their respective sets
        # TODO there has to be a better way to do this
        # TODO do this inside class StreetNetwork?
        for osmid, tags, members in self.all_osm_relations.values():
            if "landuse" in tags:
                if tags["landuse"] == "residential":
                    self.residential_nodes = self.residential_nodes | self.get_all_child_nodes(osmid)
                if tags["landuse"] == "industrial":
                    self.industrial_nodes = self.industrial_nodes | self.get_all_child_nodes(osmid)
                if tags["landuse"] == "commercial":
                    self.commercial_nodes = self.commercial_nodes | self.get_all_child_nodes(osmid)
        for osmid, tags, refs in self.all_osm_ways.values():
            if "landuse" in tags:
                if tags["landuse"] == "residential":
                    self.residential_nodes = self.residential_nodes | self.get_all_child_nodes(osmid)
                if tags["landuse"] == "industrial":
                    self.industrial_nodes = self.industrial_nodes | self.get_all_child_nodes(osmid)
                if tags["landuse"] == "commercial":
                    self.commercial_nodes = self.commercial_nodes | self.get_all_child_nodes(osmid)
        for osmid, tags, coords in self.all_osm_nodes.values():
            if "landuse" in tags:
                if tags["landuse"] == "residential":
                    self.residential_nodes = self.residential_nodes | self.get_all_child_nodes(osmid)
                if tags["landuse"] == "industrial":
                    self.industrial_nodes = self.industrial_nodes | self.get_all_child_nodes(osmid)
                if tags["landuse"] == "commercial":
                    self.commercial_nodes = self.commercial_nodes | self.get_all_child_nodes(osmid)
        street_network_nodes = set(self.street_network.get_nodes())
        self.connected_residential_nodes = self.residential_nodes & street_network_nodes
        self.connected_industrial_nodes = self.industrial_nodes & street_network_nodes
        self.connected_commercial_nodes = self.commercial_nodes & street_network_nodes

    def coords_callback(self, coords):
        for osmid, lon, lat in coords:
            self.coords[osmid] = dict([(self.LATITUDE, lat), (self.LONGITUDE, lon)])
            self.bounds["min_lat"] = min(self.bounds["min_lat"], lat)
            self.bounds["min_lon"] = min(self.bounds["min_lon"], lon)
            self.bounds["max_lat"] = max(self.bounds["max_lat"], lat)
            self.bounds["max_lon"] = max(self.bounds["max_lon"], lon)

    def nodes_callback(self, nodes):
        for node in nodes:
            self.all_osm_nodes[node[0]] = node

    def ways_callback(self, ways):
        for way in ways:
            self.all_osm_ways[way[0]] = way

    def relations_callback(self, relations):
        for relation in relations:
            self.all_osm_relations[relation[0]] = relation

    def get_all_child_nodes(self, osmid):
        # given any OSM id, construct a set of the ids of all descendant nodes
        if osmid in self.all_osm_nodes.keys():
            return set([osmid])
        if osmid in self.all_osm_relations.keys():
            children = set()
            for osmid, osmtype, role in self.all_osm_relations[osmid][2]:
                children = children | self.get_all_child_nodes(osmid)
            return children
        if osmid in self.all_osm_ways.keys():
            children = set()
            for ref in self.all_osm_ways[osmid][2]:
                children.add(ref)
            return children
        return set()

    def length_euclidean(self, id1, id2):
        # calculate distance on a 2D plane assuming latitude and longitude
        # form a planar uniform coordinate system (obviously not 100% accurate)
        p1 = self.coords[id1]
        p2 = self.coords[id2]
        # assuming distance between to degrees of latitude to be approx.
        # 66.4km as is the case for Hamburg, and distance between two
        # degrees of longitude is always 111.32km
        dist = sqrt( ((p2[self.LATITUDE]-p1[self.LATITUDE])*111.32)**2
                     + ((p2[self.LONGITUDE]-p1[self.LONGITUDE])*66.4)**2 )
        return dist*1000 # return distance in m

    def length_haversine(self, id1, id2):
        # calculate distance using the haversine formula, which incorporates
        # earth curvature
        # see http://en.wikipedia.org/wiki/Haversine_formula
        lat1 = self.coords[id1][self.LATITUDE]
        lon1 = self.coords[id1][self.LONGITUDE]
        lat2 = self.coords[id2][self.LATITUDE]
        lon2 = self.coords[id2][self.LONGITUDE]
        lat1, lon1, lat2, lon2 = map(radians, [lat1, lon1, lat2, lon2])
        dlon = lon2 - lon1
        dlat = lat2 - lat1
        a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
        c = 2 * asin(sqrt(a))
        return 6367000 * c # return distance in m
Beispiel #4
0
    # how fast can a car drive to ensure the calculated breaking distance?
    potential_speed = sqrt(settings["braking_deceleration"] * available_braking_distance * 2) # m/s
    # cars respect speed limit
    actual_speed = min(max_speed, potential_speed * 3.6) # km/h

    return actual_speed


if __name__ == "__main__":
    def out(*output):
        for o in output:
            print o,
        print ''

    street_network = StreetNetwork()
    street_network.add_node(1, 0, 0)
    street_network.add_node(2, 0, 0)
    street_network.add_node(3, 0, 0)
    street_network.add_street((1, 2,), 10, 50)
    street_network.add_street((2, 3,), 100, 140)

    trips = dict()
    trips[1] = [3]

    sim = Simulation(street_network, trips, out)
    for step in range(10):
        print "Running simulation step", step + 1, "of 10..."
        sim.step()
    # done