rustsim_crowd/lib.rs
1//! Microscopic crowd locomotion models for rustsim.
2//!
3//! This crate implements the five microscopic pedestrian models catalogued at
4//! <https://pedestriandynamics.org/models/> in pure 2-D continuous space
5//! plus a **layered 2.5-D** extension in the [`threed`] module for
6//! multi-storey environments (stations, airports, stadiums, malls).
7//!
8//! It is called `rustsim-crowd` rather than `rustsim-pedestrian` because
9//! the same physics apply equally to cyclists, evacuees, queue-formers,
10//! and generic self-propelled agents.
11//!
12//! | Module | Model | Class | Primary references |
13//! |---|---|---|---|
14//! | [`social_force`] | Social Force | Force-based, 2nd order | Helbing & Molnár 1995; Helbing, Farkas & Vicsek 2000 |
15//! | [`collision_free_speed`] | Collision-Free Speed | Velocity-based, 1st order | Tordeux, Chraibi & Seyfried 2016 |
16//! | [`generalized_centrifugal_force`] | Generalized Centrifugal Force | Force-based, 2nd order | Chraibi, Seyfried & Schadschneider 2010 |
17//! | [`optimal_steps`] | Optimal Steps | Discrete-step utility | Seitz & Köster 2012 |
18//! | [`anticipation_velocity`] | Anticipation Velocity | Velocity-based, 1st order | Xu, Chraibi & Seyfried 2021 |
19//! | [`threed`] | Layered 2.5-D Social Force | Per-floor 2-D physics + vertical connectors | Industry standard (JuPedSim, MassMotion, Legion) |
20//!
21//! # API shape
22//!
23//! Every 2-D model shares the same three-type contract defined by the
24//! [`PedestrianModel`] trait:
25//!
26//! - [`Pedestrian`] — the shared per-agent state (position, velocity, radius,
27//! desired speed, destination).
28//! - [`WallSegment`] — a 2-D line segment describing a static obstacle.
29//! - `Params` — a model-specific parameter bundle living inside each module.
30//!
31//! Each model exposes:
32//!
33//! - a `Params` struct with stable literature/engineering defaults.
34//! - explicit [`calibration`] helpers for deployments that must enforce a
35//! published speed-density envelope such as Weidmann (1993).
36//! - a unit struct implementing [`PedestrianModel`] so callers can swap
37//! models behind a trait object or generic bound.
38//! - a free `step(peds, walls, params, dt)` function (deprecated since
39//! `0.0.3`; O(n²) reference path retained for parity tests). Production
40//! callers use `step_scratch` (zero-alloc) or `step_with_grid`
41//! (broadphase) instead.
42//!
43//! ```
44//! use rustsim_crowd::prelude::*;
45//!
46//! let mut peds = vec![Pedestrian::new(
47//! [0.0, 0.0],
48//! [0.0, 0.0],
49//! 0.25,
50//! 1.34,
51//! [10.0, 0.0],
52//! )];
53//! let walls: Vec<WallSegment> = Vec::new();
54//! let params = social_force::Params::default();
55//! // Production hot path: zero-alloc, broadphase-accelerated.
56//! let mut scratch = Scratch::new(recommended_cell_size(
57//! social_force::neighbor_cutoff(¶ms),
58//! ));
59//! social_force::step_scratch(&mut peds, &walls, ¶ms, 0.05, &mut scratch);
60//! ```
61//!
62//! # Design constraints
63//!
64//! - Pure `f64`, SoA-friendly internals, no interior mutability.
65//! - `step_scratch(peds, walls, params, dt, &mut scratch)` is the
66//! **zero-alloc hot path**: allocate one [`broadphase::Scratch`] per
67//! simulation and reuse it tick-after-tick. `step_with_grid` takes a
68//! caller-owned [`NeighborGrid`] and allocates one `Vec<[f64; 2]>`
69//! per tick; `step` is the O(n²) reference path with no broadphase.
70//! - Determinism: every `step_*` variant is a deterministic function
71//! of its inputs.
72
73#![deny(missing_docs)]
74
75pub mod anticipation_velocity;
76pub mod broadphase;
77pub mod calibration;
78pub mod collision_free_speed;
79pub mod common;
80#[cfg(feature = "cuda")]
81pub mod cuda;
82pub mod error;
83pub mod generalized_centrifugal_force;
84pub mod integration;
85pub mod optimal_steps;
86#[cfg(feature = "simd")]
87pub mod simd;
88pub mod social_force;
89pub mod threed;
90
91pub use broadphase::{recommended_cell_size, NeighborGrid, Scratch};
92pub use calibration::{
93 apply_weidmann_speed_cap, apply_weidmann_speed_target, density_for_area, mean_speed,
94 CalibrationPoint, CalibrationReport, WeidmannCurve,
95};
96pub use common::{Pedestrian, PedestrianModel, WallSegment};
97pub use error::CrowdError;
98pub use integration::{
99 pack_columns_from, step_columns_f64, step_scratch_store, step_scratch_store_observed,
100 unpack_columns_into, AnticipationVelocityModel, CollisionFreeSpeedModel, CrowdAgent,
101 CrowdObserver, CrowdStep, GeneralizedCentrifugalForceModel, OptimalStepsModel,
102 SocialForceModel,
103};
104#[cfg(feature = "rayon")]
105pub use integration::{step_scratch_store_observed_par, step_scratch_store_par, CrowdStepPar};
106pub use threed::{LayeredObserver, LayeredScratch, Pedestrian3D, WallPolygon3D};
107
108/// Convenience re-exports for the common consumer path.
109pub mod prelude {
110 pub use crate::broadphase::{recommended_cell_size, NeighborGrid, Scratch};
111 pub use crate::calibration::{
112 apply_weidmann_speed_cap, apply_weidmann_speed_target, density_for_area, mean_speed,
113 CalibrationPoint, CalibrationReport, WeidmannCurve,
114 };
115 pub use crate::common::{Pedestrian, PedestrianModel, WallSegment};
116 pub use crate::error::CrowdError;
117 pub use crate::integration::{
118 pack_columns_from, step_columns_f64, step_scratch_store, step_scratch_store_observed,
119 unpack_columns_into, AnticipationVelocityModel, CollisionFreeSpeedModel, CrowdAgent,
120 CrowdObserver, CrowdStep, GeneralizedCentrifugalForceModel, OptimalStepsModel,
121 SocialForceModel,
122 };
123 #[cfg(feature = "rayon")]
124 pub use crate::integration::{
125 step_scratch_store_observed_par, step_scratch_store_par, CrowdStepPar,
126 };
127 pub use crate::threed::{
128 step_layered, step_layered_scratch, step_layered_scratch_observed, LayeredObserver,
129 LayeredScratch, Pedestrian3D, WallPolygon3D,
130 };
131 pub use crate::{
132 anticipation_velocity, collision_free_speed, generalized_centrifugal_force, optimal_steps,
133 social_force, threed,
134 };
135}