Microscopic models : granular and social force model

Microscopic crowd-simulation utilities used by Cromosim.

The module contains contact detection, force evaluation, velocity projection, pedestrian initialization and transfer helpers, sensor processing, and plotting utilities for the microscopic crowd model.

cromosim.micro.add_people_flows(dom, groups, dt, dmin_people=0, dmin_walls=0, rng=None, itermax=10, projection_method='cvxopt', flow_duration=0.0, seed=0, frustration_memory_size=10, log=True)[source]

Create pedestrians generated by time-dependent population flows.

Each group marked with "flux_per_minute" accumulates a fractional flow. Whenever the accumulated value exceeds one pedestrian, the corresponding integer number of pedestrians is created and the fractional remainder is kept in groups[...]["flux"] for the next call.

Parameters:
domDomain

Domain in which pedestrians are created.

groupssequence of dict

Population-group definitions.

dtfloat

Simulation time step.

dmin_peoplefloat, optional

Minimum pedestrian-pedestrian distance during initialization.

dmin_wallsfloat, optional

Minimum pedestrian-wall distance during initialization.

rngnumpy.random.RandomState or None, optional

Random-number generator. A new generator is created when None.

itermaxint, optional

Maximum number of overlap-removal iterations.

projection_methodstr, optional

Projection solver used while removing overlaps.

flow_durationfloat, optional

Duration, in seconds, represented by the current flow update.

seedint, optional

Seed used only when a new random generator is created. 0 requests a non-deterministic seed.

frustration_memory_sizeint, optional

Number of entries allocated for frustration history.

logbool, optional

If True, emit flow-initialization diagnostics.

Returns:
dict or None

Dictionary containing newly created pedestrians, or None when no pedestrian must be added during this call.

cromosim.micro.append_people(people, people_to_add)[source]

Append a newly generated pedestrian batch to an existing population.

cromosim.micro.check_people_in_box(dom, box, xyrv, dest_names, rng, log=True)[source]

Relocate pedestrians that are outside a box or an admissible region.

The function repeatedly resamples invalid positions until every pedestrian lies inside the computational domain, inside box and outside destination exclusion zones.

Parameters:
domDomain

Domain object used for geometry and destination checks.

boxsequence of float

Bounding box [xmin, xmax, ymin, ymax].

xyrvnumpy.ndarray, shape (n_people, 4)

Pedestrian state array.

dest_namessequence of str

Destination name for each pedestrian.

rngnumpy.random.RandomState

Random-number generator.

logbool, optional

If True, emit relocation diagnostics.

Returns:
infobool

True if at least one pedestrian had to be relocated, otherwise False.

xyrvnumpy.ndarray

Updated pedestrian states. The input array is modified in place.

cromosim.micro.compute_contacts(dom, xyrv, dmax)[source]

Compute active pedestrian-pedestrian and pedestrian-wall contacts.

Pedestrian pairs are identified with a scipy.spatial.cKDTree. Wall contacts are obtained from the domain wall-distance field.

Parameters:
domDomain

Domain object providing wall distances and wall-distance gradients.

xyrvnumpy.ndarray, shape (n_people, 4)

Pedestrian state array with columns x, y, radius r and velocity coefficient v.

dmaxfloat

Maximum gap distance for an active contact. A contact is retained when dij < dmax.

Returns:
numpy.ndarray, shape (n_contacts, 5)

Contact rows (i, j, dij, eij_x, eij_y). Pedestrian-pedestrian contacts satisfy i < j. Wall contacts use j = -1.

cromosim.micro.compute_forces(F, Fwall, xyrv, contacts, U, Vd, lambda_, delta, k, eta)[source]

Compute social, overlap and friction forces for all pedestrians.

The social-force contribution includes the directional weighting associated with the pedestrian viewing direction. Overlap and tangential friction forces are added for active contacts.

Parameters:
Ffloat

Pedestrian-pedestrian social-force amplitude.

Fwallfloat

Pedestrian-wall social-force amplitude.

xyrvnumpy.ndarray, shape (n_people, 4)

Pedestrian state array with columns x, y, radius r and velocity coefficient v.

contactsnumpy.ndarray, shape (n_contacts, 5)

Contact rows (i, j, dij, eij_x, eij_y).

Unumpy.ndarray, shape (n_people, 2)

Current pedestrian velocities.

Vdnumpy.ndarray, shape (n_people, 2)

Desired pedestrian velocities.

lambda_float

Directional-dependence coefficient in [0, 1]. The value 1 gives an isotropic interaction.

deltafloat

Characteristic interaction distance in the exponential social force.

kfloat

Contact stiffness used when pedestrians overlap.

etafloat

Tangential friction coefficient.

Returns:
numpy.ndarray, shape (n_people, 2)

Total force applied to each pedestrian.

cromosim.micro.create_people_at_positions(nn, rgb_color, dest_name, radius_distribution, velocity_distribution, viewing_angle_distribution, mass_distribution, dom, rng, log=True)[source]

Create pedestrians at positions encoded by an RGB map color.

Pixels matching rgb_color define the available positions. If more positions than pedestrians are available, a random subset is selected.

Parameters:
nnint

Number of pedestrians to create.

rgb_colorsequence of int

RGB triplet identifying admissible pixels in the domain image.

dest_namestr

Initial destination assigned to every created pedestrian.

radius_distributionsequence

Distribution specification ["uniform", min, max] or ["normal", mean, std] for pedestrian radii.

velocity_distributionsequence

Distribution specification for velocity coefficients.

viewing_angle_distributionsequence

Distribution specification for half viewing angles, in degrees.

mass_distributionsequence

Distribution specification for pedestrian masses.

domDomain

Domain containing the RGB image and geometric metadata.

rngnumpy.random.RandomState

Random-number generator.

logbool, optional

If True, emit initialization diagnostics.

Returns:
xyrvnumpy.ndarray, shape (nn, 4)

New pedestrian states (x, y, r, v).

dest_nameslist of str

Destination name for each pedestrian.

viewnumpy.ndarray, shape (nn,)

Half viewing angle for each pedestrian, clipped to [0, 90] degrees.

massnumpy.ndarray, shape (nn,)

Pedestrian masses.

cromosim.micro.create_people_in_box(nn, box, dest_name, radius_distribution, velocity_distribution, viewing_angle_distribution, mass_distribution, dom, rng, log=True)[source]

Create pedestrians at random admissible positions inside a box.

Radii, velocity coefficients, viewing angles and masses are sampled from the requested distributions. Positions are resampled until they belong to a region where the selected destination is admissible. Overlaps between pedestrians are not removed by this function.

Parameters:
nnint

Number of pedestrians to create.

boxsequence of float

Bounding box [xmin, xmax, ymin, ymax].

dest_namestr

Initial destination assigned to every created pedestrian.

radius_distributionsequence

Distribution specification ["uniform", min, max] or ["normal", mean, std] for pedestrian radii.

velocity_distributionsequence

Distribution specification for velocity coefficients.

viewing_angle_distributionsequence

Distribution specification for half viewing angles, in degrees.

mass_distributionsequence

Distribution specification for pedestrian masses.

domDomain

Domain object used to test destination admissibility.

rngnumpy.random.RandomState

Random-number generator.

logbool, optional

If True, emit initialization diagnostics.

Returns:
xyrvnumpy.ndarray, shape (nn, 4)

New pedestrian states (x, y, r, v).

dest_nameslist of str

Destination name for each pedestrian.

viewnumpy.ndarray, shape (nn,)

Half viewing angle for each pedestrian, clipped to [0, 90] degrees.

massnumpy.ndarray, shape (nn,)

Pedestrian masses.

cromosim.micro.find_duplicate_people(all_people, domains)[source]

Build virtual pedestrians for overlapping transit regions.

Pedestrians located inside a destination transit box are copied to the connected domain using the configured spatial shift. The reverse copy is also performed for pedestrians located in the shifted transit box.

Parameters:
all_peopledict

Mapping from domain names to pedestrian dictionaries.

domainsdict

Mapping from domain names to Domain objects.

Returns:
dict

Virtual pedestrian dictionaries for every domain.

cromosim.micro.move_people(time, dt, people, sensors)[source]

Advance pedestrian positions and update crossing sensors.

Parameters:
timefloat

Current simulation time.

dtfloat

Time step.

peopledict

Pedestrian data. The dictionary must contain at least "xyrv", "U" and "id".

sensorslist of dict

Sensor definitions and accumulated sensor data.

Returns:
peopledict

Updated pedestrian data after advancing positions by dt.

sensorslist of dict

Updated sensors. Crossing identifiers, times, intersection points and directions are appended to the corresponding sensor records.

cromosim.micro.people_initialization(dom, groups, dt, dmin_people=0, dmin_walls=0, rng=None, seed=0, itermax=10, frustration_memory_size=10, flow_duration=0.0, projection_method='cvxopt', log=True)[source]

Initialize the pedestrian population for one domain.

Flow-driven groups are processed first, followed by groups with a fixed initial population. Pedestrians are assigned identifiers and auxiliary arrays used by the microscopic model.

Parameters:
domDomain

Domain in which pedestrians are initialized.

groupssequence of dict

Population-group definitions. Each group may define "nb", "flux_per_minute", distribution specifications, "box", "color_for_positions", "destination" and "with_frustration".

dtfloat

Simulation time step.

dmin_peoplefloat, optional

Minimum pedestrian-pedestrian distance.

dmin_wallsfloat, optional

Minimum pedestrian-wall distance.

rngnumpy.random.RandomState or None, optional

Random-number generator.

seedint, optional

Seed used only when rng is None. 0 requests a non-deterministic seed.

itermaxint, optional

Maximum number of overlap-removal iterations.

frustration_memory_sizeint, optional

Number of entries allocated for frustration history.

flow_durationfloat, optional

Duration, in seconds, represented by the current flow update.

projection_methodstr, optional

Projection solver used while removing overlaps.

logbool, optional

If True, emit initialization diagnostics.

Returns:
dict or None

Initialized pedestrian dictionary, or None if no pedestrian is created.

cromosim.micro.people_update_destination(all_people, domains, thld, box=None)[source]

Update pedestrian destinations, domain transfers and removals.

Pedestrians outside the allowed geometry are removed. Pedestrians close to their current destination are either transferred to a next domain, shifted through a transit box, assigned a new destination, or removed when no next destination is defined.

Parameters:
all_peopledict

Mapping from domain names to pedestrian dictionaries.

domainsdict

Mapping from domain names to Domain objects.

thldfloat

Distance threshold used to decide whether a destination has been reached.

boxsequence of float or None, optional

Optional removal box [xmin, xmax, ymin, ymax]. If None, each domain bounding box is used.

Returns:
dict

Updated all_people mapping.

cromosim.micro.projection(dt, xyrv, contacts, Vd, Mass, dmin_people=0, dmin_walls=0, nb_iter_max=100000, rho=0.1, tol=0.01, log=False, method='cvxopt')[source]

Project desired velocities onto the non-overlapping feasible set.

The projection minimizes the mass-weighted distance to the desired velocity under linearized non-overlap constraints. Several numerical solvers are supported, including CVXOPT, MOSEK, Uzawa and the C++ Cromosim solvers.

Parameters:
dtfloat

Time step.

xyrvnumpy.ndarray, shape (n_people, 4)

Pedestrian state array with columns x, y, radius r and velocity coefficient v.

contactsnumpy.ndarray, shape (n_contacts, 5)

Contact rows (i, j, dij, eij_x, eij_y).

Vdnumpy.ndarray, shape (n_people, 2)

Desired pedestrian velocities.

Massnumpy.ndarray, shape (n_people,)

Pedestrian masses.

dmin_peoplefloat, optional

Minimum pedestrian-pedestrian distance.

dmin_wallsfloat, optional

Minimum pedestrian-wall distance.

nb_iter_maxint, optional

Maximum number of iterations for iterative solvers.

rhofloat, optional

Step parameter used by the Uzawa method.

tolfloat, optional

Solver tolerance.

logbool, optional

If True, emit solver diagnostics.

methodstr, optional

Solver name. Supported values are "cvxopt", "mosek", "uzawa", "cppuzawa", "nesterov" and "cppnesterov".

Returns:
infoint

Solver information, typically the number of iterations. -1 denotes an iterative solver that reached its iteration limit.

Bscipy.sparse.csr_matrix or None

Contact-constraint matrix.

Unumpy.ndarray, shape (n_people, 2)

Projected pedestrian velocities.

Lnumpy.ndarray or None

Contact Lagrange multipliers when available.

Pnumpy.ndarray or None

Per-pedestrian pressure estimate when multipliers are available.

frustrationsnumpy.ndarray, shape (n_people,)

Frustration measure in [0, 1] based on the loss of velocity in the desired direction.

cromosim.micro.remove_overlaps_in_box(dom, box, xyrv, dest_names, mass, dt, rng, projection_method='cvxopt', dmin_people=0, dmin_walls=0, itermax=10, log=True)[source]

Iteratively remove pedestrian overlaps inside a bounding box.

Repeated velocity projections are used to separate overlapping pedestrians. After each projection, positions are checked and invalid positions are resampled inside the requested box.

Parameters:
domDomain

Domain object.

boxsequence of float

Bounding box [xmin, xmax, ymin, ymax].

xyrvnumpy.ndarray, shape (n_people, 4)

Pedestrian states. Positions are modified in place.

dest_namessequence of str

Destination name for each pedestrian.

massnumpy.ndarray, shape (n_people,)

Pedestrian masses.

dtfloat

Time step used by the projection.

rngnumpy.random.RandomState

Random-number generator.

projection_methodstr, optional

Projection solver passed to projection().

dmin_peoplefloat, optional

Minimum pedestrian-pedestrian distance.

dmin_wallsfloat, optional

Minimum pedestrian-wall distance.

itermaxint, optional

Maximum number of outer overlap-removal iterations.

logbool, optional

If True, emit progress diagnostics.

Returns:
numpy.ndarray

Updated pedestrian states.

cromosim.micro.sensor(door, xy0, xy1, t0, t1, dist_in, dist_out)[source]

Detect pedestrian crossings of a line segment sensor.

The pedestrian trajectory during [t0, t1] is approximated by a segment. The function computes intersections with the sensor segment, crossing directions, approximate crossing times and pedestrians currently located near either side of the sensor.

Parameters:
doorarray-like, shape (4,)

Sensor segment coordinates [x0, y0, x1, y1].

xy0numpy.ndarray, shape (n_people, 2)

Pedestrian positions at time t0.

xy1numpy.ndarray, shape (n_people, 2)

Pedestrian positions at time t1.

t0float

Initial time.

t1float

Final time.

dist_infloat

Maximum distance used to identify pedestrians on the entry side.

dist_outfloat

Maximum distance used to identify pedestrians on the exit side.

Returns:
idnumpy.ndarray

Indices of pedestrians crossing the sensor.

pnumpy.ndarray

Intersection points for crossing pedestrians.

ionumpy.ndarray

Crossing directions: 1 for exits and -1 for entries.

timesnumpy.ndarray

Estimated crossing times.

entriesint

Number of entries.

exitsint

Number of exits.

id_people_innumpy.ndarray

Indices of pedestrians near the entry side.

id_people_outnumpy.ndarray

Indices of pedestrians near the exit side.