Getting started#

Welcome to the getting started guide of JuPedSim, we want to guide you through the first steps for setting up a simulation.

First things first, to use JuPedSim install it via:

pip install jupedsim

Now, you are ready to set up your first simulation with JuPedSim.

If you want to follow this Jupyter Notebook on your own machine, you can download it here.

Let’s simulate an experiment#

This is a bottleneck experiment conducted at the University of Wuppertal in 2018. You can see the basic setup of the experiment in the picture below:

../_images/040_c_56_h-.png

The data for this experiment is available here, which belongs to this experimental series and is part of the publication “Crowds in front of bottlenecks at entrances from the perspective of physics and social psychology”.

In this guide, we want to simulate the same bottleneck scenario with JuPedSim.

If you use JuPedSim in your work, please cite it using the following information from Zenodo:

DOI

Setting up the simulation geometry#

The first thing to consider when setting up a simulation is the area where the agents can move. In this scenario, we have a rectangular room with two obstacles that form a bottleneck, as displayed above. These obstacles are excluded areas from the simulation, which means that agents can not move inside these obstacles.

import shapely

geometry = shapely.Polygon(
    # complete area
    [
        (3.5, -2),
        (3.5, 8),
        (-3.5, 8),
        (-3.5, -2),
    ],
    holes=[
        # left barrier
        [
            (-0.7, -1.1),
            (-0.25, -1.1),
            (-0.25, -0.15),
            (-0.4, 0.0),
            (-2.8, 0.0),
            (-2.8, 6.7),
            (-3.05, 6.7),
            (-3.05, -0.3),
            (-0.7, -0.3),
            (-0.7, -1.0),
        ],
        # right barrier
        [
            (0.25, -1.1),
            (0.7, -1.1),
            (0.7, -0.3),
            (3.05, -0.3),
            (3.05, 6.7),
            (2.8, 6.7),
            (2.8, 0.0),
            (0.4, 0.0),
            (0.25, -0.15),
            (0.25, -1.1),
        ],
    ],
)

This leads to the following setup:

../_images/ba08bfb15e145534523a501d5cae14d06e374118afed60b1758441aa0c6b0c3c.png

In this geometric setup, we now need to define, where the agents can exit the simulation, e.g., where their target is located.

For this scenario, the exit is at the end of the bottleneck. If we would put it at the beginning of the bottleneck, the agents would disappear, hence, they wouldn’t be an obstacle for following agents.

An exit can be defined as:

exit_polygon = shapely.Polygon(
    [(-0.2, -1.9), (0.2, -1.9), (0.2, -1.7), (-0.2, -1.7)]
)

The complete setup would then look like, where the exit is shown in red:

../_images/28e3d1492db9c7eb41af54473737c9a810d8b62db4a52a8fda8693003730f8a4.png

Distribute the agents in the geometry#

The next step is to provide the initial positions of the agents in the simulation. JuPedSim provides different helper functions to automatically distribute the agents:

However, as we want to compare our simulation to the real-life experimental data, the agents in the simulation will start at the same positions as the pedestrians in the experiment. So we load the trajectory from the experiment and extract the locations at frame 0, which is the start of the experiment.

import pandas

experiment_data = pandas.read_csv(
    "demo-data/bottleneck/040_c_56_h-.txt",
    comment="#",
    sep="\t",
    header=None,
    names=["id", "frame", "x", "y", "z"],
)
start_positions = experiment_data[experiment_data.frame == 0][
    ["x", "y"]
].values

Collision-free speed model#

At first, we want to run the simulation with the Collision-free speed model. In “Collision-free speed model for pedestrian dynamics” you can find the complete description of the model. To use it in JuPedSim we need to state, that we will use this model in the creation of the simulation object.

We also need to provide the previously defined geometry and the output file, where the resulting trajectories will be stored. Here, we will use the built-in SqliteTrajectoryWriter, which will write the results as a sqlite-database.

import jupedsim as jps
import pathlib

trajectory_file = "bottleneck_cfsm.sqlite"
simulation_cfsm = jps.Simulation(
    model=jps.CollisionFreeSpeedModel(),
    geometry=geometry,
    trajectory_writer=jps.SqliteTrajectoryWriter(
        output_file=pathlib.Path(trajectory_file)
    ),
)

After we defined the simulation we need to add a goal, which the agents should target. As we already defined the exit polygon above, we can add it to the simulation as a stage. After adding the exit to the simulation, we need to create a journey containing that exit. Journeys are used to manage more complex routing situation, an explanation of the underlying routing concept can be found here.

exit_id = simulation_cfsm.add_exit_stage(exit_polygon)
journey = jps.JourneyDescription([exit_id])
journey_id = simulation_cfsm.add_journey(journey)

Now we have the setup for the simulation. But there are no agents in simulation yet, so we need to add them.

Before adding a simulation we need to define the agent specific parameters. In this example, all the agents will get the same parameters. We will now re-use the above extracted start positions of the agents.

for position in start_positions:
    simulation_cfsm.add_agent(
        jps.CollisionFreeSpeedModelAgentParameters(
            journey_id=journey_id,
            stage_id=exit_id,
            position=position,
            radius=0.12,
        )
    )

After, we have added the agents. We’ve got everything needed to start a simulation. Here, we will iterate, as long as there are agents inside the simulation, e.g., some agents have not yet reached the exit.

while simulation_cfsm.agent_count() > 0:
    simulation_cfsm.iterate()

Now, every agent has left the simulation. Let’s have a look at the result:

Hide code cell source
import pedpy
from jupedsim.internal.notebook_utils import animate, read_sqlite_file

trajectory_data, walkable_area = read_sqlite_file(trajectory_file)
speed = pedpy.compute_individual_speed(traj_data=trajectory_data, frame_step=5)
speed = speed.merge(trajectory_data.data, on=["id", "frame"], how="left")

animate(trajectory_data, walkable_area)