irsim.lib.algorithm.social_force_model#

Social Force Model (SFM) for pedestrian / mobile-agent navigation.

Independent Python implementation of the Social Force Model described in:

Helbing, D. & Molnar, P. (1995), Social force model for pedestrian dynamics. Phys. Rev. E 51:4282.

Moussaid, M., Helbing, D., Garnier, S., Johansson, A., Combe, M., Theraulaz, G. (2009), Experimental study of the behavioural mechanisms underlying self-organization in human crowds. Proc. R. Soc. B 276:2755.

The neighbor interaction is the anisotropic, velocity-aware variant from Moussaid-Helbing (2009); the obstacle term is the Helbing-Molnar (1995) summation form -- every nearby line obstacle contributes an exponentially decayed push, which (unlike a nearest-segment-only rule) lets symmetric walls cancel and keeps the agent on the centreline.

Each agent integrates Newton-like dynamics v += dt * a where a is the weighted sum of three forces:

  • desired force -- relaxation of velocity toward v0 * e_goal;

  • social force -- anisotropic repulsion from each neighbor (Moussaid-Helbing 2009 form);

  • obstacle force -- exponential repulsion summed over all line obstacles within 5 * sigma_obstacle (Helbing-Molnar 1995 form).

social_force_model evaluates these forces for one agent at a time and backs the per-object sfm behavior. SocialForceModelBatch evaluates the same forces for a whole crowd in one NumPy pass from a single state snapshot and adds the optional social-group forces of Moussaid et al. (2010); it backs the sfm group behavior.

Acknowledgement:

pedsim_ros (srl-freiburg/pedsim_ros) and its vendored libpedsim by Christian Gloor were consulted as reference implementations while writing this module.

PySocialForce (yuxiang-gao/PySocialForce) by Yuxiang Gao, a NumPy implementation of the extended social force model with social groups, inspired the batched evaluation and the social-group forces of SocialForceModelBatch.

Attributes#

Classes#

social_force_model

Social Force Model controller for a single agent.

SocialForceModelBatch

Vectorized Social Force Model for a crowd of agents.

Module Contents#

class irsim.lib.algorithm.social_force_model.social_force_model(state: list, neighbor_list: list | None = None, line_obs_list: list | None = None, vmax: float = 1.5, step_time: float = 0.1, relaxation_time: float = 0.5, force_factor_desired: float = 1.0, force_factor_social: float = 2.1, force_factor_obstacle: float = 10.0, sigma_obstacle: float = 0.8, lambda_importance: float = 2.0, gamma: float = 0.35, n_angular: float = 2.0, n_velocity: float = 3.0, neighbor_range: float = 10.0, safety_radius: float = 0.0)[源代码]#

Social Force Model controller for a single agent.

The interface mirrors reciprocal_vel_obs so the two algorithms are interchangeable from a behavior method.

参数:
  • state (list) -- Agent state [x, y, vx, vy, radius, vx_des, vy_des, theta].

  • neighbor_list (list) -- Other moving/static circular agents [[x, y, vx, vy, radius], ...].

  • line_obs_list (list) -- Line obstacles [[x1, y1, x2, y2], ...].

  • vmax (float) -- Speed cap applied after the velocity update.

  • step_time (float) -- Integration step dt.

  • relaxation_time (float) -- tau in the desired-force term.

  • force_factor_desired (float) -- Weight alpha_D on the desired force.

  • force_factor_social (float) -- Weight alpha_S on the social force.

  • force_factor_obstacle (float) -- Weight alpha_O on the obstacle force.

  • sigma_obstacle (float) -- Decay length of the obstacle repulsion.

  • lambda_importance (float) -- Weight of relative velocity in the interaction direction (lambda in Moussaïd 2009).

  • gamma (float) -- Sets the interaction range B = gamma * ||t||.

  • n_angular (float) -- Angular sharpness n for the sideways force.

  • n_velocity (float) -- Angular sharpness n' for the slowdown force.

  • neighbor_range (float) -- Max distance for an agent to count as a social-force neighbor.

  • safety_radius (float) -- Personal-space buffer subtracted from the agent-to-agent distance inside the social-force exponential. 0 reproduces the upstream behavior (point agents). > 0 shifts the decay closer-in so the repulsion saturates at 2 * safety_radius of centre-to-centre clearance, effectively giving each agent a body radius for SFM.

state#
neighbor_list#
line_obs_list#
vmax = 1.5#
step_time = 0.1#
relaxation_time = 0.5#
force_factor_desired = 1.0#
force_factor_social = 2.1#
force_factor_obstacle = 10.0#
sigma_obstacle = 0.8#
lambda_importance = 2.0#
gamma = 0.35#
n_angular = 2.0#
n_velocity = 3.0#
neighbor_range = 10.0#
safety_radius = 0.0#
update(state: list, neighbor_list: list, line_obs_list: list | None = None) → None[源代码]#

Refresh the per-step inputs without re-instantiating.

cal_vel() → list[源代码]#

Integrate one SFM step and return the new global velocity.

返回:

Updated velocity [vx, vy], clipped to vmax.

返回类型:

list[float]

desired_force() → list[源代码]#

Relaxation toward the desired velocity v0 * e_goal.

The desired velocity is supplied directly via state[5:7].

social_force() → list[源代码]#

Anisotropic neighbor repulsion (Moussaid-Helbing 2009).

Iterates over all neighbors within neighbor_range and sums their contribution.

obstacle_force() → list[源代码]#

Exponential repulsion summed over all nearby line obstacles.

The upstream reference uses only the single nearest obstacle, which oscillates in symmetric environments (two parallel walls flip which one is "nearest" each step). We use the Helbing-Molnar (1995) summation form instead: every segment within 5 * sigma_obstacle contributes an exponentially decayed push, so symmetric walls cancel and the agent walks the centreline. The integration is also clamped against overlap (distance < 0 would otherwise make exp(-distance/sigma) explode).

class irsim.lib.algorithm.social_force_model.SocialForceModelBatch(states, neighbor_states=None, line_obs_list=None, social_groups: list[list[int]] | None = None, vmax: float = 1.5, step_time: float = 0.1, relaxation_time: float = 0.5, force_factor_desired: float = 1.0, force_factor_social: float = 2.1, force_factor_obstacle: float = 10.0, sigma_obstacle: float = 0.8, lambda_importance: float = 2.0, gamma: float = 0.35, n_angular: float = 2.0, n_velocity: float = 3.0, neighbor_range: float = 10.0, safety_radius: float = 0.0, force_factor_coherence: float = 2.0, force_factor_group_repulsion: float = 1.0, group_repulsion_threshold: float | None = None, force_factor_gaze: float = 3.0, gaze_vision_angle: float = 90.0)[源代码]#

Vectorized Social Force Model for a crowd of agents.

Evaluates the same desired, social and obstacle forces as social_force_model for N agents at once from one state snapshot. Every agent therefore reacts to the same instant, so the result does not depend on the order in which agents are stepped, and the pairwise social term is array math over all N x (N + M) pairs instead of a Python loop.

Agents can optionally be partitioned into social groups (people walking together). Members of a group receive the three extra forces of Moussaid et al. (2010), in the formulation used by pedsim_ros:

  • coherence -- pull toward the group's centre of mass, ramping in smoothly (tanh) once a member is further than (size - 1) / 2 metres from it;

  • repulsion -- push apart members whose centres come closer than group_repulsion_threshold;

  • gaze -- brake along the velocity, f = -alpha * v, when the other members' centre of mass lies outside a gaze_vision_angle cone around the walking direction; alpha is the missing head rotation in radians, so an agent slows down until it can see its group again.

引用

Moussaid, M., Perozo, N., Garnier, S., Helbing, D., Theraulaz, G. (2010), The walking behaviour of pedestrian social groups and its impact on crowd dynamics. PLoS ONE 5(4): e10047.

PySocialForce, yuxiang-gao/PySocialForce -- NumPy implementation of the extended social force model whose batched force evaluation and group forces this class follows.

参数:
  • states (array-like) -- (N, 8) agent states [x, y, vx, vy, radius, vx_des, vy_des, theta]; theta is carried for the caller and not used by the forces.

  • neighbor_states (array-like) -- (M, 5) circular neighbours that are not part of the batch, [[x, y, vx, vy, radius], ...] (robots driven by other behaviors, circular obstacles). They push batch agents but are not moved.

  • line_obs_list (array-like) -- (K, 4) line obstacles [[x1, y1, x2, y2], ...].

  • social_groups (list[list[int]] | None) -- Index lists into states; each agent may appear in at most one group. None or [] disables the group forces.

  • vmax (float) -- Speed cap applied after the velocity update.

  • step_time (float) -- Integration step dt.

  • relaxation_time (float) -- tau in the desired-force term.

  • force_factor_desired (float) -- Weight on the desired force.

  • force_factor_social (float) -- Weight on the social force.

  • force_factor_obstacle (float) -- Weight on the obstacle force.

  • sigma_obstacle (float) -- Decay length of the obstacle repulsion.

  • lambda_importance (float) -- Weight of relative velocity in the interaction direction.

  • gamma (float) -- Sets the interaction range B = gamma * ||t||.

  • n_angular (float) -- Angular sharpness n for the sideways force.

  • n_velocity (float) -- Angular sharpness n' for the slowdown force.

  • neighbor_range (float) -- Agents further apart than this ignore each other in the social force.

  • safety_radius (float) -- Personal-space buffer subtracted from the agent-to-agent distance inside the social-force exponential.

  • force_factor_coherence (float) -- Weight on the group coherence force.

  • force_factor_group_repulsion (float) -- Weight on the intra-group repulsion force.

  • group_repulsion_threshold (float | None) -- Centre-to-centre distance below which two group members repel each other. None uses the sum of their radii (states[:, 4]), i.e. members push apart as soon as their discs touch.

  • force_factor_gaze (float) -- Weight on the group gaze force.

  • gaze_vision_angle (float) -- Half-angle, in degrees, of the cone around the walking direction inside which the group's centre of mass is considered visible.

vmax = 1.5#
step_time = 0.1#
relaxation_time = 0.5#
force_factor_desired = 1.0#
force_factor_social = 2.1#
force_factor_obstacle = 10.0#
sigma_obstacle = 0.8#
lambda_importance = 2.0#
gamma = 0.35#
n_angular = 2.0#
n_velocity = 3.0#
neighbor_range = 10.0#
safety_radius = 0.0#
force_factor_coherence = 2.0#
force_factor_group_repulsion = 1.0#
group_repulsion_threshold = None#
force_factor_gaze = 3.0#
gaze_vision_angle = 90.0#
social_groups: list[numpy.ndarray] = []#
update(states, neighbor_states=None, line_obs_list=None, social_groups: list[list[int]] | None = None) → None[源代码]#

Refresh the per-step inputs without re-instantiating.

参数:
  • states -- (N, 8) agent states.

  • neighbor_states -- (M, 5) external circular neighbours.

  • line_obs_list -- (K, 4) line obstacles.

  • social_groups -- New group partition, or None to keep the current one. Pass [] to switch the group forces off.

property n: int#

Number of agents in the batch.

cal_vel() → numpy.ndarray[源代码]#

Integrate one SFM step for every agent.

返回:

(N, 2) updated world-frame velocities, each clipped to vmax.

返回类型:

np.ndarray

desired_force() → numpy.ndarray[源代码]#

Relaxation toward the desired velocity states[:, 5:7].

social_force() → numpy.ndarray[源代码]#

Anisotropic neighbour repulsion (Moussaid-Helbing 2009).

Each agent sums the contribution of every other batch agent and every external neighbour closer than neighbor_range. Matches social_force_model.social_force() term by term.

obstacle_force() → numpy.ndarray[源代码]#

Exponential repulsion summed over all nearby line obstacles.

Same rule as social_force_model.obstacle_force(): every segment within 5 * sigma_obstacle + radius of an agent's centre contributes, the decay is clamped at the body surface, and a segment passing exactly through the centre pushes along +x.

coherence_force() → numpy.ndarray[源代码]#

Pull each member toward its group's centre of mass.

The pull is (com - p) * (tanh(d - d_max) + 1) / 2 with d_max = (size - 1) / 2 metres, the smooth variant of the paper's step rule used by pedsim_ros.

group_repulsive_force() → numpy.ndarray[源代码]#

Push apart group members that come too close.

Each pair closer than group_repulsion_threshold (or the sum of the two radii when that is None) contributes the raw offset p_self - p_other.

gaze_force() → numpy.ndarray[源代码]#

Brake when the rest of the group falls out of view.

With phi the angle between the walking direction v and the other members' centre of mass, the force is -(phi - phi_vis) * v when phi exceeds gaze_vision_angle and zero otherwise. A stationary member has no walking direction and gets no gaze force.

irsim.lib.algorithm.social_force_model.state_a = [0.0, 0.0, 1.0, 0.0, 0.3, 1.0, 0.0, 0.0]#