pythonnetworkxosmnx

oneway:bicycle=no in OSMNX graph with network_type='bike'


I am working on an asssessment of bicycle infrastructure along common routes within european cities. In the process I encountered the following problem:

Within Europe it is quite common to allow cyclists to pass oneway streets in both directions (I don't know if that is a thing in North America). The correspondent edges in OSM are tagged with oneway=yes and oneway:bicycle=no.

Using the osmnx.k_shortest_paths function in a graph with network_type='bike', I found out that riding along oneway streets in the opposite direction is avoided, even though it is legal.

This is the code I used for testing. For motorized transport, the Marienstraße in its northern section is only allowed to be used heading north. For bicycles it is free in both directions. Nevertheless the routing function makes a detour when going southwards. In the other (generally allowed) direction the street is used. I included a test, whether the edges are tagged correctly (which they are).

import osmnx as ox


add_tags = (['oneway:bicycle'])
ox.settings.useful_tags_way = ox.settings.useful_tags_way + add_tags
G = ox. graph_from_place("Karlsruhe, Germany", network_type='bike')
start = ox.nearest_nodes(G, 8.408005310258606, 49.003891115254056,  return_dist=False)  # Kommödchen
dest = ox.nearest_nodes(G, 8.408489900323096, 48.99637841654651, return_dist=False)  # Yuki Sushi
test = ox.k_shortest_paths(G, start, dest, 1, weight='length')
test_list = list(test)
test_nodes = test_list[0]
test_edges = ox.utils_graph.route_to_gdf(G, test_nodes, weight='length')
fig, ax = ox.plot_graph_route(G, test_nodes, route_color='r', route_linewidth=5, node_size=20)

test_backwards = test = ox.k_shortest_paths(G, dest, start, 1, weight='length')
back_list = list(test_backwards)
back_nodes = back_list[0]
back_edges = ox.utils_graph.route_to_gdf(G, back_nodes, weight='length')
fig_b, ax_b = ox.plot_graph_route(G, back_nodes, route_color='r', route_linewidth=5, node_size=20)

for index, row in back_edges.iterrows():
    print(row["oneway"], row["oneway:bicycle"])

Is there a workaround to reverse the respective edges according to the oneway:bicycle tags and add them to the graph?


Solution

  • I got it myself:

    I made a GeoDataFrame from the graph and filtered for the edges the which represent one way streets which are open in both direction for bicycles:

    gdf_nodes, gdf_edges = ox.graph_to_gdfs(G, nodes=True, edges=True, node_geometry=True, fill_edge_geometry=True)
    filtered_rows = gdf_edges[(gdf_edges['oneway'] == True) & (gdf_edges['oneway:bicycle'] == 'no')]
    

    I copied those edges and reversed them myself:

    filtered_rows = filtered_rows.reset_index()
    modified_rows = filtered_rows.copy()
    modified_rows['u'], modified_rows['v'] = filtered_rows['v'], filtered_rows['u']
    modified_rows['reversed'] = True
    modified_rows['geometry'] = sh.reverse(filtered_rows['geometry'])
    

    Then I added the edges to the GeoDataFrame and then re-converted it into a graph:

    modified_rows.set_index(['u', 'v', 'key'], inplace=True)
    gdf_edges_new = gpd.GeoDataFrame(pd.concat([gdf_edges, modified_rows], ignore_index=False))
    G_new = ox.graph_from_gdfs(gdf_nodes, gdf_edges_new, graph_attrs=None)
    

    Bicycle routing through the applying roads works perfectly now.