This package contains a Python implementation of the Helbing-Molnár-Farkas-Vicsek Social Force Model. The code was created for a master thesis and is still in active development.
Feel free to clone or fork. For questions regarding the model you can contact me at [myfullname] at gmail dot com.
Just checkout the repository and run python setup.py
.
- Add optimizations to social force calculations.
- Add GUI to allow run-time parameter tuning and testing.
- Add unit tests.
- Let parameterloader give errors for unknown parameters.
- Make parameterloader case insensitive.
You can use a .yaml parameter file to load and build a world. The following parameters are configurable:
world_width
(float) - default10.0
- width (x) of domainworld_height
(float) - default10.0
- height (y) of domaincontinuous_domain
(boolean) - defaultFalse
- whether the domain should wrap aroundstep_size
(float) - default0.05
- simulation step sizedefault_desired_velocity
(float) - default1.3
- default desired velocity of pedestriansdefault_maximum_velocity
(float) - default2.6
- default maximum velocity of pedestriansdefault_relaxation_time
(float) - default2.0
- default relaxation time of pedestriansdesired_velocity_importance
(float) - default0.8
- between 0.0 and 1.0, lower means the velocity is more dependent on neighbourhood velocityinteractive_distance_threshold
(float) - default2.0
- distance after which objects and pedestrians are no longer used in interactive force calculationstarget_distance_threshold
(float) - default0.13
- maximum distance to target for it to be considered reachedrepulsion_coefficient
(float) - default2000 Newton
falloff_length
(float) - default0.08 meters
body_force_constant
(float) - default12000 kg / s²
friction_force_constant
(float) - default24000 kg / ms
quad_tree_threshold
(integer) - maximum number of pedestrians in a quad tree leafgroups
(one or more Group entities) - pedestrian groups in this simulationobstacles
(one or more Obstacle entities) - obstacles in this simulation
x
(float)y
(float)
start
(Point)end
(Point)
Default values are taken from global variables if not provided.
start_time
(float) - default0 seconds
- Time at which this group should appear in the simulationspawn_area
(Area) - The default area in which new pedestrians should spawnspawn_rate
(float) - default0 pedestrians per second
- Pedestrian spawn ratetarget_area
(Area) - The default area in which new pedestrian targets should spawntarget_path
(one or more Point entities) - The path which pedestrians should follow to get to their targetmass
(float) - default60 kg
- Mass of pedestriansradius
(float) - default0.15 m
- Radius of pedestriansdesired_velocity
(float) - Desired velocity of pedestriansmaximum_velocity
(float) - Maximum velocity of pedestriansrelaxation_time
(float) - Relaxation time of pedestriansnum_pedestrians
(integer) - The number of pedestrians to spawn with default parameterspedestrians
(one or more Pedestrian entities) - Pedestrians to add to this group
Pedestrians should always be part of a group. Variables that are not set are inferred from the group.
start
(Point) - Spawn pointtarget
(Point) - Target pointtarget_path
(one or more Point entities) - The path which this pedestrian should follow to get to their target.mass
(float) - Mass of pedestrianradius
(float) - Radius of pedestriandesired_velocity
(float) - Desired velocity of pedestrianmaximum_velocity
(float) - Maximum velocity of pedestrianrelaxation_time
(float) - Relaxation time of pedestrian
points
(one or more Point entities) - series of points. Line segments are drawn between pairs of points.
The following parameter file creates a 10x10 box connected to a 10x4 exit tunnel. The box starts with 100 pedestrians spawned at random positions in the box. Each pedestrian then attempts to navigate through the tunnel using a predefined target path, towards an off-screen target beyond the tunnel.
world_height: 10
world_width: 20
groups:
- num_pedestrians: 100
spawn_area:
start:
x: 0.5
y: 0.5
end:
x: 9.5
y: 9.5
target_area:
start:
x: 20.0
y: 2.5
end:
x: 25.0
y: 7.5
target_path:
- x: 9.5
y: 5.0
- x: 21.0
y: 5.0
obstacles:
- points:
- x: 10.0
y: 0.0
- x: 10.0
y: 2.5
- x: 11.0
y: 3.5
- x: 20.0
y: 3.5
- points:
- x: 20.0
y: 6.5
- x: 11.0
y: 6.5
- x: 10.0
y: 7.5
- x: 10.0
y: 10.0
The following Python file loads the parameters from the YAML file, creates a simulation, adds some measurements and runs and plots the situation.
import socialforcemodel as sfm
import numpy as np
import matplotlib.pyplot as plt
def average_speed(world):
velocities = []
for group in world.groups:
for p in group.pedestrians:
velocities.append(p.speed)
return np.mean(velocities)
def avg_num_neighbours(world):
counts = []
for group in world.groups:
for p in group.pedestrians:
counts.append(p.get_measurement('neighbourhood', 'num_neighbours'))
return np.mean(counts)
def main(args):
loader = sfm.ParameterLoader(args.file)
world = loader.world
world.update()
world.add_measurement(average_speed)
world.add_measurement(avg_num_neighbours)
figure = world.plot()
figure.savefig("img/0.png",
bbox_inches = 'tight',
pad_inches = 0.1)
figure.clear()
plt.close(figure)
for step in range(args.steps):
print "Step {}".format(step + 1)
if not world.step():
break
world.update()
if step % 5 == 4:
figure = world.plot()
figure.savefig("img/" + str((step + 1) / 5) + ".png",
bbox_inches = 'tight',
pad_inches = 0.1)
figure.clear()
plt.close(figure)
np.savetxt("measurements.txt", world.measurements)
if __name__ == '__main__':
import argparse
import sys
parser = argparse.ArgumentParser()
parser.add_argument('file', help='YAML-file')
parser.add_argument('-s', '--steps', help='Number of steps', type=int, default=500)
args = parser.parse_args(sys.argv[1:])
main(args)