Simulating a Car Driving Across London in 20 Lines of Python

Simulating a Car Driving Across London in 20 Lines of Python

Well, 19 lines to be precise, but it didn't have the same ring to it.

Ever thought you could mimic a car's jaunt across London without leaving your desk or touching a steering wheel? With the magic of Python (magic being a not so subtle theme of this blog post) and a few clever libraries, we're about to embark on a virtual tour through the Holborn's winding streets, all from the comfort of our pyjamas. And the best part? It only takes 20 lines of Python. Yes - fewer lines than there are in a Shakespearean sonnet.

(I'm assuming you already know the basics of getting Python up and running, if not then see: https://www.python.org/about/gettingstarted/)

The Magical Quartet

To pull off this feat, we're enlisting the help of four trusty Python libraries:

  • OSMnx: For conjuring up the map of London - we will zone in on Holborn for this example.

  • NetworkX: For navigating the labyrinth of London's roads without getting utterly lost.

  • Matplotlib and celluloid: For painting our journey on the canvas of London's streets.

You can install these with pip by typing this into your terminal:

pip install osmnx networkx matplotlib celluloid

The Spellbook

Incantation 1: Summoning the Libraries

import osmnx as ox
import random
from matplotlib import pyplot as plt
from celluloid import Camera
import networkx as nx

Now, let's pull London's street network out of the ether.

Incantation 2: Importing Holborn

# Latitude and Longitude for a point in Holborn, London
latitude = 51.5175
longitude = -0.117

# Create a graph from a point
G = ox.graph_from_point((latitude, longitude), dist=500, dist_type='bbox', network_type='drive')

# Ensure the graph is strongly connected
G = ox.utils_graph.get_largest_component(G, strongly=True)

Ensuring the graph is strongly connected is crucial when simulating routes or analyzing networks, especially in the context of urban street networks for tasks like simulating a car's journey. A graph is considered strongly connected if there is a path between all pairs of vertices in the graph.

Now... choosing our starting and finishing points for the car randomly because who doesn't love a bit of unpredictability?

Incantation 3: Choosing our start and finish point

# Select two random nodes
origin, destination = random.sample(list(G.nodes), 2)

Finding the shortest path without having to ask a local for directions.

Incantation 4: The Pathfinding Potion

# Compute the shortest path
shortest_path = nx.shortest_path(G, origin, destination, weight='length')

nx.shortest_path is used to find the shortest path between two nodes in a graph, based on Dijkstra's algorithm or the Bellman-Ford algorithm, depending on the nature of the edge weights.

And for the grand finale, let's reveal our journey on the map, showcasing our Pythonic prowess.

Incantation 5: Revealing the Route

# Visualisation
fig, ax = plt.subplots()  # Create a matplotlib figure and axes.
camera = Camera(fig)  # Prepare the camera for capturing each frame.

# Instead of plotting point by point, accumulate the points in the path for each frame.
for i in range(1, len(shortest_path) + 1):
    ox.plot_graph(G, ax=ax, show=False, close=False, node_size=0, bgcolor='k')  # Redraw the graph for each frame.
    ox.plot_graph_route(G, shortest_path[:i], route_linewidth=6, node_size=0, bgcolor='k', route_color='r', orig_dest_node_size=100, ax=ax, show=False, close=False)  # Plot the route up to the current point.
    camera.snap()  # Capture the frame.

animation = camera.animate()  # Create the animation.
animation.save('car_journey.gif', writer='imagemagick')  # Save the animation as a GIF.

You may need to install imagemagick, on a Mac you can use homebrew in the terminal with the following command:

brew install imagemagick

The Grand Tour

Voila! With these incantations combined, we've just simulated a car's trip across London.

In just 20 lines of Python code, we've managed to simulate a car driving across London, offering a glimpse into the potent capabilities of modern programming married with urban data. Yet, this example merely tiptoes around the perimeter of a vast playground, one where the tools at our disposal can forge paths through not just cities, but through the very fabric of how we understand and interact with our environment.

Did you find this article valuable?

Support Harry Munro by becoming a sponsor. Any amount is appreciated!