-
-
Notifications
You must be signed in to change notification settings - Fork 272
Example Project :GIS-Based Traffic Simulation with Mesa #160
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
12ff2cf
Example Project :GIS-Based Traffic Simulation with Mesa
PRIYANSHU2026 76654d6
done
PRIYANSHU2026 db8fe95
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] ae59ba6
Update model.py
PRIYANSHU2026 6e37c28
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 253e1ee
Fix ruff formatting
EwoutH f7e7a38
Clean up notebook
EwoutH d017b36
Update readme.md
PRIYANSHU2026 6614c6a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] bc6c17d
Update readme.md
PRIYANSHU2026 1e354ca
Update readme.md
PRIYANSHU2026 3f3b3f7
OSMnx: Use bbox, warn about future order change
EwoutH 5eae9b7
Fix bug in agent.step
EwoutH File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Binary file added
BIN
+4.01 MB
gis/GIS-Based Traffic Simulation with Mesa/Data/Banglore_traffic_congestion.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+4.14 MB
gis/GIS-Based Traffic Simulation with Mesa/Data/bangalore_traffic_congestion.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
263 changes: 263 additions & 0 deletions
263
gis/GIS-Based Traffic Simulation with Mesa/GIS-Based Traffic Simulation with Mesa.ipynb
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| # agent.py | ||
|
|
||
| import mesa | ||
|
|
||
|
|
||
| class VehicleAgent(mesa.Agent): | ||
| def __init__(self, unique_id, model, vehicle_type, route=None): | ||
| super().__init__(unique_id, model) | ||
| self.vehicle_type = vehicle_type # Assign vehicle type (car, truck, bike) | ||
| self.route = route # Assign the route for the vehicle | ||
| self.current_step = 0 # Initialize the current step in the route | ||
|
|
||
| def step(self): | ||
| if self.route and self.current_step < len(self.route): | ||
| next_node = self.route[self.current_step] | ||
| x = self.model.space.G.nodes[next_node]["x"] - self.model.min_x | ||
| y = self.model.space.G.nodes[next_node]["y"] - self.model.min_y | ||
| self.model.space.move_agent(self, (x, y)) | ||
| self.current_step += 1 # Move to the next step in the route | ||
| else: | ||
| pass # Optionally, handle reaching the end of the route |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| import random | ||
|
|
||
| import mesa | ||
| import networkx as nx | ||
| import osmnx as ox | ||
| from agent import VehicleAgent | ||
|
|
||
|
|
||
| class TrafficGeoSpace(mesa.space.ContinuousSpace): | ||
| def __init__(self, G, min_x, min_y, max_x, max_y, crs="EPSG:3857"): | ||
| x_max = max_x - min_x | ||
| y_max = max_y - min_y | ||
| super().__init__(x_max, y_max, False) | ||
| self.G = G # Assign the OSMnx graph to the space | ||
| self.crs = crs # Coordinate Reference System | ||
|
|
||
|
|
||
| class TrafficModel(mesa.Model): | ||
| def __init__(self, G, num_vehicles, min_x, min_y, max_x, max_y): | ||
| super().__init__() | ||
| self.schedule = mesa.time.RandomActivation(self) | ||
| self.space = TrafficGeoSpace(G, min_x, min_y, max_x, max_y) | ||
| self.min_x = min_x | ||
| self.min_y = min_y | ||
| self.max_x = max_x | ||
| self.max_y = max_y | ||
| self.create_vehicles(num_vehicles) | ||
|
|
||
| def create_vehicles(self, num_vehicles): | ||
| vehicle_types = ["car", "truck", "bike"] | ||
| for i in range(num_vehicles): | ||
| start_point = ( | ||
| random.uniform(self.min_y, self.max_y), | ||
| random.uniform(self.min_x, self.max_x), | ||
| ) | ||
| end_point = ( | ||
| random.uniform(self.min_y, self.max_y), | ||
| random.uniform(self.min_x, self.max_x), | ||
| ) | ||
| start_node = ox.distance.nearest_nodes( | ||
| self.space.G, X=start_point[1], Y=start_point[0] | ||
| ) | ||
| end_node = ox.distance.nearest_nodes( | ||
| self.space.G, X=end_point[1], Y=end_point[0] | ||
| ) | ||
|
|
||
| try: | ||
| route = nx.shortest_path( | ||
| self.space.G, source=start_node, target=end_node, weight="length" | ||
| ) | ||
| vehicle_type = random.choice(vehicle_types) | ||
| vehicle = VehicleAgent(i, self, vehicle_type=vehicle_type, route=route) | ||
| start_position = ( | ||
| self.space.G.nodes[start_node]["x"] - self.min_x, | ||
| self.space.G.nodes[start_node]["y"] - self.min_y, | ||
| ) # Adjust coordinates | ||
| self.space.place_agent(vehicle, start_position) | ||
| self.schedule.add(vehicle) | ||
| except nx.NetworkXNoPath: | ||
| pass # Skip this vehicle if no route is found | ||
|
|
||
| def step(self): | ||
| self.schedule.step() | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
|
|
||
|
|
||
| # GIS-Based Traffic Simulation with Mesa | ||
|
|
||
|
|
||
|
|
||
| ## Overview | ||
|
|
||
| This project simulates urban traffic congestion using the Mesa agent-based modeling framework and OSMnx for extracting road network data from OpenStreetMap. It visualizes traffic patterns and congestion in a critical urban area in Bangalore, India. The simulation includes different vehicle types and their movement on the road network, and the results are animated into a GIF to showcase the traffic dynamics over time. | ||
|
|
||
| ## Why We Need This | ||
|
|
||
| ### Problem Definition | ||
|
|
||
| High vehicle density and complex road networks are significant contributors to traffic congestion in Indian cities, especially in densely populated urban areas. This issue affects millions of travelers, leading to: | ||
|
|
||
| - Increased travel duration | ||
| - Higher fuel consumption | ||
| - Elevated pollution levels | ||
|
|
||
| In cities like Bangalore, also known as the Tech Hub or Silicon Valley of India, these problems are exacerbated by rapid urbanization and technological growth. | ||
|
|
||
| ### Objective | ||
|
|
||
| By developing and refining this traffic simulation project, we aim to deliver more effective and adaptable solutions for managing traffic congestion in Indian cities. The project has the potential to: | ||
|
|
||
| - Improve traffic flow and reduce congestion | ||
| - Decrease travel time and fuel consumption | ||
| - Lower pollution levels | ||
| - Enhance the overall quality of life for urban residents | ||
|
|
||
| ## Features | ||
|
|
||
| - **Urban Traffic Simulation**: Models traffic flow using various vehicle types (cars, trucks, bikes). | ||
| - **OSMnx Integration**: Utilizes OSMnx to extract and visualize road networks from OpenStreetMap. | ||
| - **Animated Visualization**: Generates an animated GIF showing traffic patterns and vehicle movements. | ||
| - **Dynamic Visualization**: Updates the visualization in real-time to reflect vehicle positions on the map. | ||
|
|
||
| ## Mesa is Playing a Main Role in This Model | ||
| Mesa provides a straightforward and efficient framework to create, manage, and simulate the movement of vehicles on a road network. It allows for the simple creation of agents (vehicles) that follow predefined paths, interact within a given space, and produce simulation results without unnecessary complexity. | ||
|
|
||
| **Mesa** is used because it enables you to build a functional and effective traffic simulation without overcomplicating the model. Its integration with other libraries like **OSMnx** and **NetworkX** ensures that the model remains easy to understand and maintain, focusing on delivering practical insights rather than adding complexity. | ||
|
|
||
| ## Requirements | ||
|
|
||
| - **Python 3.11** | ||
| - **OSMnx**: `pip install osmnx` | ||
| - **NetworkX**: `pip install networkx` | ||
| - **Folium**: `pip install folium` | ||
| - **Mesa**: `pip install mesa` | ||
| - **PIL**: `pip install pillow` | ||
|
|
||
|
|
||
|
|
||
| 1. **Update Bounding Box Coordinates** | ||
|
|
||
| Modify the `north`, `south`, `east`, and `west` variables in the script to reflect the area you want to simulate. | ||
|
|
||
| 2. **Run the Simulation** | ||
|
|
||
| Execute the script to run the traffic simulation and generate the animated GIF: | ||
|
|
||
|
|
||
|
|
||
| 3. **View the Results** | ||
|
|
||
| The resulting animated GIF will be saved in the `Data` directory. You can view it directly from your file explorer or display it within a Jupyter Notebook using: | ||
|
|
||
|
|
||
|
|
||
| ## Code Overview | ||
|
|
||
| - **TrafficGeoSpace**: Defines the space in which the agents move, based on the road network graph. | ||
| - **VehicleAgent**: Represents individual vehicles, including their routes and movement. | ||
| - **TrafficModel**: Manages the simulation, creating vehicles and stepping through the simulation. | ||
| - **Visualization**: Uses Folium to create maps and convert HTML maps to PNG images, which are then compiled into an animated GIF. | ||
|
|
||
| ## Future Work | ||
|
|
||
| The project can be extended to address the following aspects: | ||
|
|
||
| - **Advanced Traffic Management**: Incorporate real-time traffic data and predictive analytics for dynamic traffic management. | ||
| - **Integration with Smart City Solutions**: Connect with IoT sensors and smart traffic lights for a more integrated approach. | ||
| - **Scenario Testing**: Simulate various scenarios such as road closures, construction, or major events to evaluate their impact on traffic. | ||
|
|
||
| ## Acknowledgments | ||
|
|
||
| - **OSMnx**: For providing easy access to OpenStreetMap data. | ||
| - **Mesa**: For the agent-based modeling framework. | ||
| - **Folium**: For interactive map visualizations. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| import io | ||
| import os | ||
|
|
||
| import folium | ||
| import networkx as nx | ||
| import osmnx as ox | ||
| from model import TrafficModel, VehicleAgent | ||
| from PIL import Image | ||
|
|
||
| # Bounding box coordinates for Bangalore | ||
| # Note that OSMnx 2.0 uses (north, south, east, west) order, so OSMnx < 2 is required (tested on 1.9.4) | ||
| # See https://github.com/gboeing/osmnx/pull/1196 | ||
| north, south, east, west = 12.976, 12.961, 77.599, 77.579 | ||
| bbox = (north, south, east, west) | ||
|
|
||
| # Create a graph from the bounding box using the bbox parameter | ||
| G = ox.graph_from_bbox(bbox=bbox, network_type="drive") | ||
|
|
||
| # Extract graph bounds for the TrafficGeoSpace | ||
| min_x = min(nx.get_node_attributes(G, "x").values()) | ||
| max_x = max(nx.get_node_attributes(G, "x").values()) | ||
| min_y = min(nx.get_node_attributes(G, "y").values()) | ||
| max_y = max(nx.get_node_attributes(G, "y").values()) | ||
|
|
||
| # Running the TrafficModel simulation | ||
| num_vehicles = 51 | ||
| model = TrafficModel(G, num_vehicles, min_x, min_y, max_x, max_y) | ||
|
|
||
| # Ensure the directory exists | ||
| gif_dir = "Data/" | ||
| os.makedirs(gif_dir, exist_ok=True) | ||
|
|
||
| # Running the simulation and updating the Folium map | ||
| map_images = [] | ||
| for step in range(10): # Run for 10 steps | ||
| model.step() | ||
|
|
||
| # Create a new map for each step | ||
| temp_map = folium.Map( | ||
| location=[(north + south) / 2, (east + west) / 2], zoom_start=15 | ||
| ) | ||
|
|
||
| # Add the road network to the map | ||
| edges = ox.graph_to_gdfs(G, nodes=False, edges=True) | ||
| for _, row in edges.iterrows(): | ||
| points = [ | ||
| (row["geometry"].coords[i][1], row["geometry"].coords[i][0]) | ||
| for i in range(len(row["geometry"].coords)) | ||
| ] | ||
| folium.PolyLine(points, color="blue", weight=2.5, opacity=1).add_to(temp_map) | ||
|
|
||
| # Add vehicles to the map | ||
| for vehicle in model.schedule.agents: | ||
| if isinstance(vehicle, VehicleAgent): | ||
| if vehicle.current_step > 0: | ||
| # Ensure vehicle has moved | ||
| position_node = vehicle.route[vehicle.current_step - 1] | ||
| vehicle_position = ( | ||
| model.space.G.nodes[position_node]["y"], | ||
| model.space.G.nodes[position_node]["x"], | ||
| ) | ||
| color = ( | ||
| "red" | ||
| if vehicle.vehicle_type == "car" | ||
| else "blue" | ||
| if vehicle.vehicle_type == "truck" | ||
| else "green" | ||
| ) | ||
| folium.CircleMarker( | ||
| location=vehicle_position, radius=5, color=color, fill=True | ||
| ).add_to(temp_map) | ||
| else: | ||
| print(f"Vehicle {vehicle.unique_id} has not started its route yet.") | ||
|
|
||
| # Save the map state as an image | ||
| img_data = temp_map._to_png(5) | ||
| img = Image.open(io.BytesIO(img_data)) | ||
| map_images.append(img) | ||
| print(f"Step {step} image captured.") | ||
|
|
||
| # Create an animated GIF from the saved map images | ||
| gif_path = os.path.join(gif_dir, "bangalore_traffic_congestion.gif") | ||
| map_images[0].save( | ||
| gif_path, save_all=True, append_images=map_images[1:], duration=500, loop=0 | ||
| ) | ||
|
|
||
| print( | ||
| "Simulation complete. Check the Data/ directory for the Bangalore traffic congestion animation." | ||
| ) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.