MicroSim is an agent-based car following traffic simulator. It employs a highly parallelized GPU implementation that is fast enough to run simulations on large-scale demand and networks within a few minutes - metropolitan and regional scale with hundreds of thousands of nodes and edges and millions of trips
- CMAKE 3.10
- Boost 1.65
- CUDA (used versions: 10.0 in Ubuntu)
- gcc (used versions: 7.5.0 in Ubuntu)
- g++ (used versions: 7.5.0 in Ubuntu)
- Qt5 (used versions: 5.9.7 in Ubuntu)
- Python (used versions: 3.6.5 in Ubuntu)
Once the necessary dependencies are installed, add CUDA lib path to system paths:
export PATH=/usr/local/cuda-10.0/bin:$PATH
export LIBRARY_PATH=/usr/local/cuda-10.0/lib64:$LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/cuda-10.0/lib64:$LD_LIBRARY_PATH
You can also add the export
lines at the end of your user's ~/.bashrc
to
avoid re-entering them in each session.
Clone the repo in your home directory with:
git clone https://github.com/cb-cities/microsim.git && cd microsim/LivingCity
Create Makefile:
mkdir build && cd build && cmake ../
Compile:
make clean && make -j8
Run unit tests
./microsim_test
Run simulation
./microsim
Simulation parameters are set in command_line_options.ini
- Read through the reference papers to understand a)IDM model.; b) Lanemap design
- Read through the Deign Principles
- Read through the Program Architecture
- Design your own test cases and pass through all tests
- Use the python analysis program to understand the simulation behaviour
- Try on real-world networks
There are three levels abstraction for the program: Agent, Intersection, Edge .
An Agent is a vehicle with a certain type (only car at current version). An Intersection (node in the network) stores queues at all directions. An edge (link in the network) is the road that agents interact with each other.
An agent exists either in an intersection or on an edge.
Agents interact with each other on an edge with fixed simple rules (IDM).
Intersections are source or sink that feed/free agents into/from edges.
It is possible to have different types of agent, and different types of interactions among them. (future works)
Property: IDM parameters: abT -> Can be different -> Car/Truck/Else
Interaction Rules: IDM car following + Lane change. (All on the edge)
Property: List of queues at every possible direction
Interaction Rule (with edges): Place a stop sign at the entrance if the queue is full (Upstream edge); Feed into downstream edge if it has enough space in a round robin way (Downstream edge). Note; each intersection contains an initialization queue, which is used to initialize agents to the edge. At each step, at most one queue will be discharged to avoid space conflicts.
Property: Array of lanes with agents on them; upstream/downstream counts; average travel time (weight)
Interaction Rule (with intersections): Feed by the upstream intersection, supply agents to the downstream intersection. Queuing occurs if the corresponding queue in the downstream intersection is full.
Input:
nodes.csv
Header: osmid,x,y,ref,highway,index
Note: index must be unique and sequential (from 0 to n)
edges.csv
Header: uniqueid,osmid_u,osmid_v,edge_length,lanes,speed_mph,u,v
Note: uniqueid must be unique! On default, each edge will be constructed twice (two directions); u ,v correspond to node index
Od.csv
Header: origin,destination,dep_time
Note: origin, destination correspond to node index, dep_time is in seconds
Output:
Edge_data_time.csv
Header: eid,u,v,upstream_count,downstream_count,average_travel_time(s)
Agents_data_time.csv
Header: aid,ori,dest,type,status,travel_dist(m),travel_time(s),ave_speed(m/s),num_slowdown,num_lane_change,num_in_queue
Simulation Configuration: Command_line_options.init
NETWORK_PATH=../tests/scenarios/case1/
OD_PATH =../tests/scenarios/case1/od.csv
START=32400
END=61200
SHOW_BENCHMARKS=false
SAVE_PATH=./case1_results/
SAVE_INTERVAL = 100
Note: all time unit is in second.
Parameter Configuration:
struct IDMParametersCar {
float a = 0.557040909258405; // acceleration
float b = 2.9020578588167; // break
float T = 0.5433027817144876; // Time heading
float s_0 = 1.3807498735425845; // min car following dis
};
All the information about the network is stored here.
Initialization:
Read node and edge data -> construct network using the sp code -> prepare initial edge weights (free flow travel time) \
Play with the network_test.cpp for a deeper understanding
All the information about the agent (origin, destination, vehicle type, departure time) is stored here
Initialization:
Read origin destination -> read departure time -> read agent types -> construct a vector of agents (defined in agent.h)\
Play with the od_test.cpp for a deeper understanding
Convert the 2d network to 1d lanemap (edge data; intersection data) for GPU access.
Initialization (edge_data):
Iterate through each edge -> copy the edge information from network (graph_) to lanemap (edgesData_) -> construct the correspondence id map (mid2eid_,eid2mid_)
-> calculate the flattened length of the edge (number of cells used) -> go to the next edge \
Initialization (intersection_data):
Iterate through each node -> iterate each in_edge/out_edge pairs -> construct each in/out pair as a queue for the intersection
Note: each vertex (node) is an intersection.
Play with the lanemap_test.cpp for a deeper understanding
Route_finding <-> simulation
Route_finding:
Use the contraction hierarchy algorithm for route finding:
Initialize the ch using the network object -> go through all the agents to construct the od pairs
-> run rh to find routes for each agent -> record each agent’s designed path (agent.route, a sequence of lanemap edge ids)
SimulateInGPU:
- Allocate an appropriate amount of memory on the cuda device then copy the CPU data to there (init_cuda)
- From start_time to end_time, simulate the movement of each agent at the simulation time step (time resolution 0.5 second) (cuda_simulate)
- Save the simulation results (time-snap for agents and edges) at each save_interval
- Free GPU memory (finish_cuda)
Cuda_simulate:
- Change map (switch the read and write map: read from the previous time-step map and write to an empty map)
- Simulate agents movements on edges (kernel_trafficSimulation)
- Simulate agents movements on intersections (kernel_intersectionOneSimulation)
kernel_trafficSimulation GPU parallel computation for each agent\
kernel_intersectionOneSimulation GPU parallel computation for each intersection\
This repository and code have been developed and maintained by Renjie Wu. This work heavily derives from Pavan Yedavalli's Microsimulation Analysis for Network Traffic Assignment and Ignacio Garcia Dorado's Automatic Urban Modeling project.