Traffic Accident Risk Analysis
Contents
Introduction
This page introduces a NetLogo-based simulation that models traffic accident risk. The goal is to understand how road conditions, traffic density, and driver behavior intertwine to create or mitigate accidents. Various research sources underscore the need for a systematic approach to traffic safety, illustrating how driver reliability, infrastructure, and cultural factors shape accident outcomes (Sadauskas, 2011; Gstalter & Fastenmeier, 2010; TSK Praha, 2020; Nordfjærn et al., 2011).
Definition of the Problem
Road traffic accidents remain a pressing public health challenge, especially with the steady growth in vehicle numbers worldwide (Sadauskas, 2011). This proliferation escalates the likelihood of collisions, injuries, and fatalities. A robust traffic safety strategy thus necessitates examining:
Road conditions (from good to very bad).
Driver behavior and risk homeostasis (adjusting behavior based on perceived safety).
Environmental and societal factors that influence compliance with safety rules (Nordfjærn et al., 2011).
Moreover, the complexity of urban intersections can amplify error rates, as drivers face higher cognitive loads and multiple conflict points (Gstalter & Fastenmeier, 2010). In city contexts, baseline accident rates still vary considerably depending on infrastructure, as seen in real-world data (TSK Praha, 2020).
Method
A systematic approach to traffic safety integrates engineering, enforcement, and education — often referred to as the “Triple E” (Sadauskas, 2011):
Engineering: Vehicle and road design improvements (e.g., signage, intersections, lighting).
Education: Public awareness, driver training programs targeting risk perception and behavior.
Enforcement: Legal measures (speed limits, penalties) ensuring compliance with traffic rules.
Human Reliability Analysis (HRA) has also been adapted to driving tasks to quantify driver error probabilities at intersections (Gstalter & Fastenmeier, 2010). By defining “correct” driver actions and measuring deviations, one can estimate how road geometry, age, and psycho-social factors alter driver reliability.
Model
This simulation uses NetLogo to create a grid of patches representing:
Road segments: Assigned good, bad, or very bad condition.
Intersections: Potentially with traffic lights.
Cars (turtles): Move according to lane rules and can trigger accidents based on speed, congestion, and driver-error-rate.
Key points:
Accident Probability: Derived from a base driver-error-rate, amplified by intersection complexity, road condition, and local traffic density (Gstalter & Fastenmeier, 2010; Nordfjærn et al., 2011).
Baseline Rates: Inspired by real accident data (e.g., TSK Praha’s ročenka dopravy or Accident risks of different weather conditions) (TSK Praha, 2020) (Malin 2017).
Systematic Approach: Reflects suggestions for engineering (road condition logic), education (driver-error slider), and enforcement (speed constraints) in modeling different scenarios (Sadauskas, 2011).
Interface
High Density, Poor Roads
Because there are 100 cars with a fairly high driver-error-rate (0.05), multiple accidents occurred (10 total). However, they tended to happen later in the simulation (average time until accident over 300 ticks). Most cars (90 out of 100) still reached their destination—likely because accident-duration is very short (1 tick), so blocked patches quickly returned to normal. The relatively high base speed (0.8) also increased mobility, helping more cars finish faster, but also contributed to a moderate accident rate.
Low Density, Strict Limits
Fewer cars (50), but also a much lower base speed (0.3), so cars move more slowly—leading to a higher average travel time (over 200 ticks). Because driver-error-rate is only 0.01 (lower chance of human error) and 70% roads are good, only 3 accidents occurred. Even with slow speed, many cars still took a long time to finish, as shown by the high travel time. Almost all cars managed to complete or crash within the time frame, with 47 successful arrivals.
Moderate Density, Extended Accident Duration
Compared to the second screenshot, the big difference is accident-duration = 90 (very long). Even though speed is still 0.3 and the road condition/distribution is the same, the accident count has climbed to 13, and 16% of the cars ended up in accidents. Because accidents last 90 ticks on a patch, any collision severely disrupts traffic, likely forcing more cars to queue or collide. Despite that, 67 cars did manage to exit, though the blocked patches would have contributed to higher accident numbers and more emergent congestion.
Conclusion
This NetLogo simulation allows users to vary key parameters—such as base speed, number of cars (density), road condition (good to very bad), driver-error rate, and accident duration—then observe metrics like average travel time, distance/time until accident, and accident hotspots. Results show that poor roads and high driver-error rates sharply increase collisions, while long accident durations intensify congestion. Conversely, safer infrastructure, lower driver-error rates, and faster incident clearance foster smoother traffic flow and fewer crashes, underlining the value of integrated traffic safety strategies.
Code
Below is the NetLogo code implementing the simulation structure (patch definitions, accident logic, congestion metrics, etc.). Users can copy and paste it into a NetLogo environment to run their own experiments. For a complete listing, see the setup, go, and supporting procedures:
globals [
;; Sliders / Switch in Interface:
;; - number-of-cars (int)
;; - road-spacing (int)
;; - base-speed (float)
;; - driver-error-rate (float)
;; - accident-duration (int)
;; - traffic-lights? (boolean switch)
;; Statistics
total-cars-reached-destination
total-cars-accident ;; how many cars died in accidents (cumulative)
accident-count ;; how many total accidents have started
average-speed
average-congestion
accident-percentage
sum-travel-time ;; sum of time in system for all cars that exit
count-completed-cars ;; how many cars reached destination
average-travel-time ;; output metric
accident-count-good
accident-count-bad
accident-count-very-bad
sum-time-until-accident
sum-distance-until-accident
average-time-until-accident
average-distance-until-accident
]
patches-own [
is-road? ;; boolean: is this patch part of a road?
is-intersection? ;; boolean: is this patch an intersection?
lane-direction ;; forced heading: 0, 90, 180, 270, or -1 if intersection
traffic-light? ;; does this patch have a traffic light?
light-state ;; true=green, false=red
has-accident? ;; boolean: accident currently on this patch?
accident-lifetime ;; integer: how many ticks remain for this accident?
road-condition ;; 0=good, 1=bad, 2=very bad (affects accident prob)
]
breed [ cars car ]
cars-own [
speed
max-speed
stopped-ticks
destination ;; patch or nobody
birth-tick ;; store the tick when the car is created
distance-traveled ;; accumulates how far the car has moved
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; 1. SETUP ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to setup
clear-all
;; Initialize stats
set total-cars-reached-destination 0
set total-cars-accident 0
set accident-count 0
set average-speed 0
set average-congestion 0
set sum-travel-time 0
set count-completed-cars 0
set average-travel-time 0
set accident-count-good 0
set accident-count-bad 0
set accident-count-very-bad 0
set sum-time-until-accident 0
set sum-distance-until-accident 0
set average-time-until-accident 0
set average-distance-until-accident 0
setup-roads
setup-intersections
setup-traffic-lights
setup-road-conditions
reset-ticks
create-initial-cars
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; 2. CREATE ROADS (TWO LANE, ONE-WAY) ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to setup-roads
ask patches [
set is-road? false
set is-intersection? false
set traffic-light? false
set light-state false
set has-accident? false
set accident-lifetime 0
set lane-direction 0
set road-condition 0
set pcolor green
]
;; 2-lane roads in x or y dimension
let road-patches patches with [
(abs pxcor mod road-spacing <= 1) or
(abs pycor mod road-spacing <= 1)
]
ask road-patches [
set is-road? true
set pcolor grey
]
;; Assign forced lane headings for non-intersection road patches
ask road-patches [
let x-road? (abs pxcor mod road-spacing <= 1)
let y-road? (abs pycor mod road-spacing <= 1)
;; purely vertical lane: pick 0 or 180
if (x-road? and not y-road?) [
ifelse (pxcor mod 2 = 0)
[ set lane-direction 0 ] ;; "northbound"
[ set lane-direction 180 ] ;; "southbound"
]
;; purely horizontal lane: pick 90 or 270
if (y-road? and not x-road?) [
ifelse (pycor mod 2 = 0)
[ set lane-direction 90 ] ;; "eastbound"
[ set lane-direction 270 ] ;; "westbound"
]
]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; 3. INTERSECTIONS ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to setup-intersections
ask patches with [is-road?] [
let x-road? (abs pxcor mod road-spacing <= 1)
let y-road? (abs pycor mod road-spacing <= 1)
;; Intersection = patch that is both x-road & y-road
if (x-road? and y-road?) [
set is-intersection? true
set pcolor yellow
set lane-direction -1 ;; means "all directions possible here"
]
]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; 4. TRAFFIC LIGHTS ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to setup-traffic-lights
if traffic-lights? [
;; Turn on lights at each intersection
ask patches with [is-intersection?] [
set traffic-light? true
set light-state true
]
]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; 5. ROAD CONDITIONS ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to setup-road-conditions
let sum-prob (good-road-probability + bad-road-probability)
ask patches with [is-road?] [
let r random-float 1
ifelse (r < good-road-probability) [
;; (1) "Good" road
set road-condition 0
set pcolor grey
] [
ifelse (r < sum-prob) [
;; (2) "Bad" road
set road-condition 1
set pcolor (grey - 2)
;; 5% chance to become "Very Bad" instead:
if random-float 1 < 0.05 [
set road-condition 2
set pcolor orange
]
] [
set road-condition 0
set pcolor grey
]
]
]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; 6. CREATE INITIAL CARS ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to create-initial-cars
ask cars [ die ] ;; remove any old cars
let valid-starts patches with [
is-road? and
not has-accident? and
not any? cars-here
]
if not any? valid-starts [
user-message "No valid road patches for car creation!"
stop
]
create-cars min list number-of-cars (count valid-starts) [
set shape "car"
set color blue
set size 0.8
;; pick a random road patch
let start-patch one-of valid-starts
move-to start-patch
set valid-starts valid-starts with [self != start-patch]
;; If this patch is an intersection => pick a direction
ifelse ([lane-direction] of patch-here = -1)
[ set heading one-of [0 90 180 270] ]
[ set heading [lane-direction] of patch-here ]
set speed 0
set max-speed base-speed
set stopped-ticks 0
set destination nobody
set distance-traveled 0
set birth-tick ticks
]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; 7. GO (MAIN LOOP) ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to go
if not any? cars [ stop ]
update-traffic-lights
move-cars
check-accidents
clear-old-accidents
update-statistics
tick
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; 8. UPDATE TRAFFIC LIGHTS ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to update-traffic-lights
if traffic-lights? [
ask patches with [is-intersection? and traffic-light?] [
;; simple toggle every 30 ticks
if (ticks mod 30 = 0) [
set light-state not light-state
set pcolor ifelse-value light-state [green] [red]
]
]
]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; 9. MOVE CARS ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to move-cars
ask cars [
;; Force lane direction
let patch-lane [lane-direction] of patch-here
ifelse patch-lane = -1 [
;; intersection => pick a new direction each tick or once
set heading one-of [0 90 180 270]
]
[
;; normal lane => enforce that heading
set heading patch-lane
]
;; Decide if it's safe to move
let safe-to-move? true
;; Check traffic light
if [traffic-light?] of patch-here [
if not ([light-state] of patch-here) [
set safe-to-move? false
]
]
;; Check for cars ahead in same lane
if any? cars-on patch-ahead 1 [
set safe-to-move? false
]
;; Move or slow
ifelse safe-to-move? [
set speed min (list (speed + 0.1) max-speed)
forward speed
set distance-traveled distance-traveled + speed
set stopped-ticks 0
] [
set speed max (list (speed - 0.2) 0)
set stopped-ticks (stopped-ticks + 1)
]
;; if the car leaves the grid:
if not is-patch? patch-here [
set count-completed-cars (count-completed-cars + 1)
;; Add to sum-travel-time:
set sum-travel-time (sum-travel-time + (ticks - birth-tick))
;; Then die
die
]
if (max-pxcor - abs xcor) < 1 or (max-pycor - abs ycor) < 1 [
set total-cars-reached-destination (total-cars-reached-destination + 1)
set count-completed-cars (count-completed-cars + 1)
set sum-travel-time (sum-travel-time + (ticks - birth-tick))
die
]
]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; 10. ACCIDENT LOGIC (EXPANDED) ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to check-accidents
;; For each car, compute probability of an accident
ask cars [
if random-float 1 < calculate-accident-probability self [
create-accident self
]
]
end
to-report calculate-accident-probability [ c ]
;; Base accident probability from driver error
let base (driver-error-rate * 0.00025)
;; Find the patch under turtle c (using c's pxcor, pycor)
let p patch ([pxcor] of c) ([pycor] of c)
;; Road condition effect
if [road-condition] of p = 1 [
set base (base * 2)
]
if [road-condition] of p = 2 [
set base (base * 2.6)
]
;; Speed factor
let speed-ratio ([speed] of c / [max-speed] of c)
set base (base * (speed-ratio + 0.1)) ;; +0.1 so even slow cars have some chance
;; Congestion effect: how many other cars are within radius 1.5 of c
let nearby-cars count cars with [ distance c < 1.5 ]
set base (base + (nearby-cars * 0.0005))
;; Intersection effect
if [is-intersection?] of p [
set base (base * 1.5)
]
;; Cap at 1% (0.01) to avoid extreme probabilities
report min (list base 0.1)
end
to create-accident [ c ]
set accident-count (accident-count + 1)
set total-cars-accident (total-cars-accident + 1)
;; Mark the patch
let px ([pxcor] of c)
let py ([pycor] of c)
ask patch px py [
set has-accident? true
set pcolor red
set accident-lifetime accident-duration
;; Accidents by Road Condition:
if (road-condition = 0) [ set accident-count-good (accident-count-good + 1) ]
if (road-condition = 1) [ set accident-count-bad (accident-count-bad + 1) ]
if (road-condition = 2) [ set accident-count-very-bad (accident-count-very-bad + 1) ]
]
;; Time & Distance to Accident:
let time-until-accident (ticks - [birth-tick] of c)
let dist-until-accident ([distance-traveled] of c)
set sum-time-until-accident (sum-time-until-accident + time-until-accident)
set sum-distance-until-accident (sum-distance-until-accident + dist-until-accident)
;; kill the car
ask c [ die ]
end
to clear-old-accidents
;; Decrement accident-lifetime. When it hits 0, clear the patch.
ask patches with [has-accident?] [
set accident-lifetime (accident-lifetime - 1)
if (accident-lifetime <= 0) [
set has-accident? false
;; restore color based on road-condition
if (road-condition = 0) [
set pcolor grey
]
if (road-condition = 1) [
set pcolor (grey - 2)
]
if (road-condition = 2) [
set pcolor orange
]
]
]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; 11. STATISTICS & PLOTS ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to update-statistics
let car-count count cars
let total-speed 0
if car-count > 0 [
set total-speed sum [speed] of cars
set average-speed (total-speed / car-count)
]
if car-count = 0 [
set average-speed 0
]
set average-congestion count cars with [
(stopped-ticks >= 2) and (any? cars-on patch-ahead 1)
]
if number-of-cars > 0 [
set accident-percentage ((accident-count / number-of-cars) * 100)
]
;;Average travel time for cars that completed trip
if count-completed-cars > 0 [
set average-travel-time (sum-travel-time / count-completed-cars)
]
;;Averages for time & distance until accident
if accident-count > 0 [
set average-time-until-accident (sum-time-until-accident / accident-count)
set average-distance-until-accident (sum-distance-until-accident / accident-count)
]
;; Plot them
carefully [
set-current-plot "Average Speed"
plot average-speed
set-current-plot "Total Accidents"
plot accident-count
set-current-plot "Average Congestion"
plot average-congestion
] []
end
References
Sadauskas, V. (2011). Traffic safety strategies, Transport, 18(2), 79–83. DOI: 10.1080/16483840.2003.10414070
Gstalter, H., & Fastenmeier, W. (2010). Reliability of drivers in urban intersections. Accident Analysis & Prevention, 42(1), 225–234. Link
TSK Praha (2020). Ročenka dopravy – 2020. Link
Nordfjærn, T., Jørgensen, S., & Rundmo, T. (2011). A cross-cultural comparison of road traffic risk perceptions, attitudes towards traffic safety, and driver behaviour. Journal of Risk Research, 14(6), 657–684. Link
Fanny Malin (2017). Accident risks in different weather conditions. Link