Understand one-dimensional microscopic models : the Follow-the-Leader modelΒΆ
The Follow-the-Leader (FTL) model presented here is a one-dimensional microscopic model. Pedestrians are assumed to walk on a line toward a common direction and the instantaneous velocity of an individual is a function of the distance to the next individual.
We consider \(N+1\) individuals walking on a straight line in a non-periodic case or in a periodic case which means that the individual \(N+1\) is identified to the individual \(1\).
We can also consider an inertial version of the Follow-the-Leader model (an order \(2\) version) which can be seen as a one-dimensional version of the Social Force model with asymmetric forcing terms to take into account that pedestrians are influenced by their immediate neighbor in front of them.
Reference : [MF2018] Chapter 2.
Thanks to several json files given as inputs of the following script, we can combine periodic or non-periodic domain with inertial or non-inertial FTL model. Examples can be find in the directory
cromosim/examples/follow_the_leader/
To run the non-inertial FTL model in non-periodic case:
python3 follow_the_leader.py --json input_ftl_order1.json
Results:
To run the non-inertial FTL model in periodic case:
python3 follow_the_leader.py --json input_ftl_order1_periodic.json
Results:
To run the inertial FTL model in non-periodic case:
python3 follow_the_leader.py --json input_ftl_order2.json
Results:
To run the inertial FTL model in periodic case:
python3 follow_the_leader.py --json input_ftl_order2_periodic.json
Results:
Code:
cromosim/examples/follow_the_leader/follow_the_leader.py
# Authors:
# Sylvain Faure <sylvain.faure@universite-paris-saclay.fr>
# Bertrand Maury <bertrand.maury@universite-paris-saclay.fr>
#
# cromosim/examples/follow_the_leader/follow_the_leader.py
# python follow_the_leader.py --json input_ftl_order1.json
# python follow_the_leader.py --json input_ftl_order1_periodic.json
# python follow_the_leader.py --json input_ftl_order2.json
# python follow_the_leader.py --json input_ftl_order2_periodic.json
#
# License: GPL
import sys
import os
from optparse import OptionParser
import json
import numpy as np
import matplotlib.pyplot as plt
from cromosim.ftl import update_positions_ftl_order_1, update_positions_ftl_order_2
from cromosim.ftl import plot_people
plt.ion()
"""
Follow The Leader model
Models :
- "ftl_order1"
- "ftl_order2" with inertia
Domain :
- periodic
- non-periodic
"""
"""
Read the input JSON file
"""
parser = OptionParser(usage="usage: %prog [options] filename", version="%prog 1.0")
parser.add_option('--json', dest="jsonfilename",
default="input.json",
type="string",
action="store",
help="Input json filename")
opt, remainder = parser.parse_args()
with open(opt.jsonfilename) as json_file:
input = json.load(json_file)
"""
Parameters obtained from the json file
"""
# Prefix for the result path
model = input["model"]
# tau :
if (model == "ftl_order_2"):
tau = input["tau"]
prefix = input["prefix"]
if not os.path.exists(prefix):
os.makedirs(prefix)
# Number of persons : 0, 1, ..., N-1
N = input["N"]
# Length of the way [0,L]
L = input["L"]
# Periodicity : True or False
# If True : no Leader
# If False : the last person (number N-1) is the leader
periodicity = input["periodicity"]
# Final time
T = input["T"]
# Timestep
dt = input["dt"]
# The positions of the persons are drawn every "drawper" iterations
drawper = input["drawper"]
# Prescribed velocity for the Leader (only used in the non-periodic case)
if (periodicity is False):
V_leader = lambda t: eval(input["V_leader"])
# Speed function
Phi = lambda w: eval(input["speed_function"])
# To initialize the positions of the persons (regularly):
xmin_t0 = input["xmin_t0"]
xmax_t0 = input["xmax_t0"]
# To build tgrid, Nt is the number of time iterations
Nt = int(np.floor(T/dt))+1
Nt += (Nt*dt < T)
tgrid = dt*np.arange(Nt)
tgrid[-1] = min(T, tgrid[-1])
# data : array where the positions and the velocities will be stored
data = np.zeros((N, 2, Nt))
# Iteration counter
counter = 0
# Initialization
time = 0.0
Xold = np.linspace(xmin_t0, xmax_t0, N)
Vold = np.zeros(Xold.shape)
data[:, 0, counter] = Xold
shift = np.zeros(Xold.shape)
# Time loop
while (time < T-0.5*dt):
dt = min(dt, T-time)
if (model == "ftl_order_1"):
if periodicity:
X, V = update_positions_ftl_order_1(L, Xold, time, dt, Phi)
else:
X, V = update_positions_ftl_order_1(L, Xold, time, dt, Phi,
V_leader=V_leader, periodicity=periodicity)
elif (model == "ftl_order_2"):
if periodicity:
X, V = update_positions_ftl_order_2(L, Xold, Vold, time, dt,
tau, Phi)
else:
X, V = update_positions_ftl_order_2(L, Xold, Vold, time, dt,
tau, Phi, V_leader=V_leader,
periodicity=periodicity)
else:
print("Bad model name... EXIT")
sys.exit()
ind = np.where((X-Xold < 0))[0]
shift[ind] += L
data[:, 0, counter] = X + shift
data[:, 1, counter] = V
time += dt
Xold = X
Vold = V
counter += 1
if (counter % drawper == 0):
if periodicity:
plot_people(L, X, time, data, tgrid, speed_fct=Phi,
ifig=10, savefig=True,
filename=prefix+"fig_"+str(counter).zfill(6)+".png")
else:
plot_people(L, X, time, data, tgrid, V_leader=V_leader,
periodicity=periodicity, speed_fct=Phi, ifig=10,
savefig=True,
filename=prefix+"fig_"+str(counter).zfill(6)+".png")
plt.pause(0.05)
print("==> Time : ", time, " s, dt = ", dt, " counter = ", counter)
plt.ioff()
plt.show()