From 46c0bd86ba87a2380664b7556d51cb43a091656e Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Mon, 30 Dec 2024 16:37:38 +0100 Subject: [PATCH 01/52] Change version of jupedsim - This change is to make sure, I'm using my own version. - Will be reversed when I'm done --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 432200688..e821aff74 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ # Project setup ################################################################################ cmake_minimum_required(VERSION 3.22 FATAL_ERROR) -project(JuPedSim VERSION 1.3.0 LANGUAGES CXX) +project(JuPedSim VERSION 1.3.1 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) From 09001fb1896823d7060862cd15b46c8e85c909e0 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 31 Dec 2024 14:07:05 +0100 Subject: [PATCH 02/52] First version compiles TODO: _JPS_Agent_GetCollisionFreeSpeedModelV3State can not be found when importing jupedsim --- examples/example7_cfsm_v3.py | 85 ++++++ libjupedsim/CMakeLists.txt | 1 + libjupedsim/include/jupedsim/agent.h | 12 + .../jupedsim/collision_free_speed_model_v3.h | 253 ++++++++++++++++++ libjupedsim/include/jupedsim/jupedsim.h | 1 + libjupedsim/include/jupedsim/simulation.h | 18 ++ libjupedsim/include/jupedsim/types.h | 1 + libjupedsim/src/agent.cpp | 2 + .../src/collision_free_speed_model_v3.cpp | 169 ++++++++++++ libjupedsim/src/simulation.cpp | 45 ++++ libsimulator/CMakeLists.txt | 8 +- .../src/CollisionFreeSpeedModelV3.cpp | 231 ++++++++++++++++ .../src/CollisionFreeSpeedModelV3.hpp | 43 +++ .../src/CollisionFreeSpeedModelV3Builder.cpp | 12 + .../src/CollisionFreeSpeedModelV3Builder.hpp | 11 + .../src/CollisionFreeSpeedModelV3Data.hpp | 39 +++ .../src/CollisionFreeSpeedModelV3Update.hpp | 9 + libsimulator/src/GenericAgent.hpp | 2 + libsimulator/src/OperationalModelType.hpp | 1 + libsimulator/src/OperationalModelUpdate.hpp | 2 + python_bindings_jupedsim/CMakeLists.txt | 1 + python_bindings_jupedsim/agent.cpp | 4 + .../bindings_jupedsim.cpp | 2 + .../collision_free_speed_model_v3.cpp | 147 ++++++++++ python_bindings_jupedsim/simulation.cpp | 14 + python_bindings_jupedsim/wrapper.hpp | 2 + python_modules/jupedsim/jupedsim/__init__.py | 9 + python_modules/jupedsim/jupedsim/agent.py | 5 + .../models/collision_free_speed_v3.py | 153 +++++++++++ .../jupedsim/jupedsim/simulation.py | 9 + systemtest/test_model_properties.py | 44 +++ 31 files changed, 1334 insertions(+), 1 deletion(-) create mode 100644 examples/example7_cfsm_v3.py create mode 100644 libjupedsim/include/jupedsim/collision_free_speed_model_v3.h create mode 100644 libjupedsim/src/collision_free_speed_model_v3.cpp create mode 100644 libsimulator/src/CollisionFreeSpeedModelV3.cpp create mode 100644 libsimulator/src/CollisionFreeSpeedModelV3.hpp create mode 100644 libsimulator/src/CollisionFreeSpeedModelV3Builder.cpp create mode 100644 libsimulator/src/CollisionFreeSpeedModelV3Builder.hpp create mode 100644 libsimulator/src/CollisionFreeSpeedModelV3Data.hpp create mode 100644 libsimulator/src/CollisionFreeSpeedModelV3Update.hpp create mode 100644 python_bindings_jupedsim/collision_free_speed_model_v3.cpp create mode 100644 python_modules/jupedsim/jupedsim/models/collision_free_speed_v3.py diff --git a/examples/example7_cfsm_v3.py b/examples/example7_cfsm_v3.py new file mode 100644 index 000000000..f3e9eb923 --- /dev/null +++ b/examples/example7_cfsm_v3.py @@ -0,0 +1,85 @@ +#! /usr/bin/env python3 + +# Copyright © 2012-2024 Forschungszentrum Jülich GmbH +# SPDX-License-Identifier: LGPL-3.0-or-later + +import pathlib +import sys + +import jupedsim as jps +import shapely + + +def main(): + geometry = shapely.GeometryCollection(shapely.box(0, -2.5, 50, 2.5)) + exit_polygon = shapely.box(48, -2.5, 50, 2.5) + + trajectory_file = "example_6.sqlite" + simulation = jps.Simulation( + model=jps.CollisionFreeSpeedModelV2(), + geometry=geometry, + trajectory_writer=jps.SqliteTrajectoryWriter( + output_file=pathlib.Path(trajectory_file) + ), + ) + + exit_id = simulation.add_exit_stage(exit_polygon) + journey = jps.JourneyDescription([exit_id]) + journey_id = simulation.add_journey(journey) + + motivated_start_positions = jps.distribute_by_number( + polygon=shapely.box(0, -2.5, 5, 2.5), + number_of_agents=30, + distance_to_agents=0.3, + distance_to_polygon=0.2, + ) + + for position in motivated_start_positions: + simulation.add_agent( + jps.CollisionFreeSpeedModelV2AgentParameters( + journey_id=journey_id, + stage_id=exit_id, + position=position, + radius=0.12, + strength_neighbor_repulsion=8, + range_neighbor_repulsion=0.1, + strength_geometry_repulsion=5, + range_geometry_repulsion=0.1, + ) + ) + + slow_start_positions = jps.distribute_by_number( + polygon=shapely.box(15, -2.5, 20, 2.5), + number_of_agents=30, + distance_to_agents=0.3, + distance_to_polygon=0.2, + ) + + for position in slow_start_positions: + simulation.add_agent( + jps.CollisionFreeSpeedModelV2AgentParameters( + journey_id=journey_id, + stage_id=exit_id, + position=position, + radius=0.12, + strength_neighbor_repulsion=30, + range_neighbor_repulsion=0.1, + strength_geometry_repulsion=15, + range_geometry_repulsion=0.1, + v0=0.3, + ) + ) + + while simulation.agent_count() > 0: + try: + simulation.iterate() + except KeyboardInterrupt: + print("CTRL-C Recieved! Shuting down") + sys.exit(1) + print( + f"Simulation completed after {simulation.iteration_count()} iterations" + ) + + +if __name__ == "__main__": + main() diff --git a/libjupedsim/CMakeLists.txt b/libjupedsim/CMakeLists.txt index 2f500307d..6c4223036 100644 --- a/libjupedsim/CMakeLists.txt +++ b/libjupedsim/CMakeLists.txt @@ -11,6 +11,7 @@ add_library(jupedsim_obj OBJECT src/build_info.cpp src/collision_free_speed_model.cpp src/collision_free_speed_model_v2.cpp + src/collision_free_speed_model_v3.cpp src/error.cpp src/generalized_centrifugal_force_model.cpp src/geometry.cpp diff --git a/libjupedsim/include/jupedsim/agent.h b/libjupedsim/include/jupedsim/agent.h index 605ee0b13..41107c391 100644 --- a/libjupedsim/include/jupedsim/agent.h +++ b/libjupedsim/include/jupedsim/agent.h @@ -4,6 +4,7 @@ #include "collision_free_speed_model.h" #include "collision_free_speed_model_v2.h" +#include "collision_free_speed_model_v3.h" #include "error.h" #include "export.h" #include "generalized_centrifugal_force_model.h" @@ -116,6 +117,17 @@ JPS_Agent_GetSocialForceModelState(JPS_Agent handle, JPS_ErrorMessage* errorMess JUPEDSIM_API JPS_CollisionFreeSpeedModelV2State JPS_Agent_GetCollisionFreeSpeedModelV2State(JPS_Agent handle, JPS_ErrorMessage* errorMessage); +/** + * Access Collision Free Speed model V3 state. + * Precondition: Agent needs to use Collision Free Speed model V3 + * @param handle of the agent to access. + * @param[out] errorMessage if not NULL: will be set to a JPS_ErrorMessage in case of an error. + * @return state or NULL on error + */ +JUPEDSIM_API JPS_CollisionFreeSpeedModelV3State +JPS_Agent_GetCollisionFreeSpeedModelV3State(JPS_Agent handle, JPS_ErrorMessage* errorMessage); + + /** * Opaque type of an iterator over agents */ diff --git a/libjupedsim/include/jupedsim/collision_free_speed_model_v3.h b/libjupedsim/include/jupedsim/collision_free_speed_model_v3.h new file mode 100644 index 000000000..bbc4a9f0a --- /dev/null +++ b/libjupedsim/include/jupedsim/collision_free_speed_model_v3.h @@ -0,0 +1,253 @@ +/* Copyright © 2012-2024 Forschungszentrum Jülich GmbH */ +/* SPDX-License-Identifier: LGPL-3.0-or-later */ +#pragma once + +#include "error.h" +#include "export.h" +#include "operational_model.h" +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Opaque type for a Collision Free Speed Model V3 Builder + */ +typedef struct JPS_CollisionFreeSpeedModelV3Builder_t* JPS_CollisionFreeSpeedModelV3Builder; + +/** + * Creates a Collision Free Speed Model V3 builder. + * @return the builder + */ +JUPEDSIM_API JPS_CollisionFreeSpeedModelV3Builder JPS_CollisionFreeSpeedModelV3Builder_Create(); + +/** + * Creates a JPS_OperationalModel of type Collision Free Speed Model V3 from the + * JPS_CollisionFreeSpeedModelV3Builder. + * @param handle the builder to operate on + * @param[out] errorMessage if not NULL: will be set to a JPS_ErrorMessage in case of an error + * @return a JPS_CollisionFreeSpeedModelV3 or NULL if an error occured. + */ +JUPEDSIM_API JPS_OperationalModel JPS_CollisionFreeSpeedModelV3Builder_Build( + JPS_CollisionFreeSpeedModelV3Builder handle, + JPS_ErrorMessage* errorMessage); + +/** + * Frees a JPS_CollisionFreeSpeedModelV3Builder + * @param handle to the JPS_CollisionFreeSpeedModelV3Builder to free. + */ +JUPEDSIM_API void +JPS_CollisionFreeSpeedModelV3Builder_Free(JPS_CollisionFreeSpeedModelV3Builder handle); + +/** + * Opaque type of Collision Free Speed V3 model state + */ +typedef struct JPS_CollisionFreeSpeedModelV3State_t* JPS_CollisionFreeSpeedModelV3State; + +/** + * Read strength neighbor repulsion of this agent. + * @param handle of the Agent to access. + * @return strength neighbor repulsion of this agent + */ +JUPEDSIM_API double JPS_CollisionFreeSpeedModelV3State_GetStrengthNeighborRepulsion( + JPS_CollisionFreeSpeedModelV3State handle); + +/** + * Write strength neighbor repulsion of this agent. + * @param handle of the Agent to access. + * @param strengthNeighborRepulsion of this agent. + */ +JUPEDSIM_API void JPS_CollisionFreeSpeedModelV3State_SetStrengthNeighborRepulsion( + JPS_CollisionFreeSpeedModelV3State handle, + double strengthNeighborRepulsion); + +/** + * Read range neighbor repulsion of this agent. + * @param handle of the Agent to access. + * @return range neighbor repulsion of this agent + */ +JUPEDSIM_API double JPS_CollisionFreeSpeedModelV3State_GetRangeNeighborRepulsion( + JPS_CollisionFreeSpeedModelV3State handle); + +/** + * Write range neighbor repulsion of this agent. + * @param handle of the Agent to access. + * @param rangeNeighborRepulsion of this agent. + */ +JUPEDSIM_API void JPS_CollisionFreeSpeedModelV3State_SetRangeNeighborRepulsion( + JPS_CollisionFreeSpeedModelV3State handle, + double rangeNeighborRepulsion); + +/** + * Read strength geometry repulsion of this agent. + * @param handle of the Agent to access. + * @return strength geometry repulsion of this agent + */ +JUPEDSIM_API double JPS_CollisionFreeSpeedModelV3State_GetStrengthGeometryRepulsion( + JPS_CollisionFreeSpeedModelV3State handle); + +/** + * Write strength geometry repulsion of this agent. + * @param handle of the Agent to access. + * @param strengthGeometryRepulsion of this agent. + */ +JUPEDSIM_API void JPS_CollisionFreeSpeedModelV3State_SetStrengthGeometryRepulsion( + JPS_CollisionFreeSpeedModelV3State handle, + double strengthGeometryRepulsion); + +/** + * Read range geometry repulsion of this agent. + * @param handle of the Agent to access. + * @return range geometry repulsion of this agent + */ +JUPEDSIM_API double JPS_CollisionFreeSpeedModelV3State_GetRangeGeometryRepulsion( + JPS_CollisionFreeSpeedModelV3State handle); + +/** + * Write strength neighbor repulsion of this agent. + * @param handle of the Agent to access. + * @param rangeGeometryRepulsion of this agent. + */ +JUPEDSIM_API void JPS_CollisionFreeSpeedModelV3State_SetRangeGeometryRepulsion( + JPS_CollisionFreeSpeedModelV3State handle, + double rangeGeometryRepulsion); + +/** + * Read e0 of this agent. + * @param handle of the Agent to access. + * @return e0 of this agent + */ +JUPEDSIM_API JPS_Point +JPS_CollisionFreeSpeedModelV3State_GetE0(JPS_CollisionFreeSpeedModelV3State handle); + +/** + * Write e0 of this agent. + * @param handle of the Agent to access. + * @param e0 of this agent. + */ +JUPEDSIM_API void +JPS_CollisionFreeSpeedModelV3State_SetE0(JPS_CollisionFreeSpeedModelV3State handle, JPS_Point e0); + +/** + * Read time gap of this agent. + * @param handle of the Agent to access. + * @return time gap of this agent + */ +JUPEDSIM_API double +JPS_CollisionFreeSpeedModelV3State_GetTimeGap(JPS_CollisionFreeSpeedModelV3State handle); + +/** + * Write time gap of this agent. + * @param handle of the Agent to access. + * @param time_gap of this agent. + */ +JUPEDSIM_API void JPS_CollisionFreeSpeedModelV3State_SetTimeGap( + JPS_CollisionFreeSpeedModelV3State handle, + double time_gap); + +/** + * Read tau of this agent. + * @param handle of the Agent to access. + * @return tau of this agent + */ +JUPEDSIM_API double +JPS_CollisionFreeSpeedModelV3State_GetTau(JPS_CollisionFreeSpeedModelV3State handle); + +/** + * Write tau of this agent. + * @param handle of the Agent to access. + * @param tau of this agent. + */ +JUPEDSIM_API void +JPS_CollisionFreeSpeedModelV3State_SetTau(JPS_CollisionFreeSpeedModelV3State handle, double tau); + +/** + * Read v0 of this agent. + * @param handle of the Agent to access. + * @return v0 of this agent + */ +JUPEDSIM_API double +JPS_CollisionFreeSpeedModelV3State_GetV0(JPS_CollisionFreeSpeedModelV3State handle); + +/** + * Write v0 of this agent. + * @param handle of the Agent to access. + * @param v0 of this agent. + */ +JUPEDSIM_API void +JPS_CollisionFreeSpeedModelV3State_SetV0(JPS_CollisionFreeSpeedModelV3State handle, double v0); + +/** + * Read radius of this agent. + * @param handle of the Agent to access. + * @return radius of this agent + */ +JUPEDSIM_API double +JPS_CollisionFreeSpeedModelV3State_GetRadius(JPS_CollisionFreeSpeedModelV3State handle); + +/** + * Write radius of this agent in meters. + * @param handle of the Agent to access. + * @param radius (m) of this agent. + */ +JUPEDSIM_API void JPS_CollisionFreeSpeedModelV3State_SetRadius( + JPS_CollisionFreeSpeedModelV3State handle, + double radius); + +/** + * Describes parameters of an Agent in Collision Free Speed Model V3 + */ +typedef struct JPS_CollisionFreeSpeedModelV3AgentParameters { + /** + * Position of the agent. + * The position needs to inside the accessible area. + */ + JPS_Point position{0, 0}; + /** + * Defines the journey this agent will take use + */ + JPS_JourneyId journeyId = 0; + /** + * Defines the current stage of its journey + */ + JPS_StageId stageId = 0; + + /** + * @param time_gap of the agents using this profile (T in the OV-function) + */ + double time_gap = 1.; + /** + *@param v0 of the agents using this profile(desired speed) double radius; + */ + double v0 = 1.2; + /** + *@param radius of the agent in 'meters' + */ + double radius = 0.2; + + /** + * Strength of the repulsion from neighbors + */ + double strengthNeighborRepulsion{8.0}; + + /** + * Range of the repulsion from neighbors + */ + double rangeNeighborRepulsion{0.1}; + + /** + * Strength of the repulsion from geometry boundaries + */ + double strengthGeometryRepulsion{5.0}; + + /** + * Range of the repulsion from geometry boundaries + */ + double rangeGeometryRepulsion{0.02}; + +} JPS_CollisionFreeSpeedModelV3AgentParameters; + +#ifdef __cplusplus +} +#endif diff --git a/libjupedsim/include/jupedsim/jupedsim.h b/libjupedsim/include/jupedsim/jupedsim.h index ba8514e32..1609ac3e2 100644 --- a/libjupedsim/include/jupedsim/jupedsim.h +++ b/libjupedsim/include/jupedsim/jupedsim.h @@ -6,6 +6,7 @@ #include "build_info.h" #include "collision_free_speed_model.h" #include "collision_free_speed_model_v2.h" +#include "collision_free_speed_model_v3.h" #include "error.h" #include "export.h" #include "generalized_centrifugal_force_model.h" diff --git a/libjupedsim/include/jupedsim/simulation.h b/libjupedsim/include/jupedsim/simulation.h index 0eaabb21d..33b222fe9 100644 --- a/libjupedsim/include/jupedsim/simulation.h +++ b/libjupedsim/include/jupedsim/simulation.h @@ -5,6 +5,7 @@ #include "agent.h" #include "collision_free_speed_model.h" #include "collision_free_speed_model_v2.h" +#include "collision_free_speed_model_v3.h" #include "error.h" #include "export.h" #include "generalized_centrifugal_force_model.h" @@ -188,6 +189,23 @@ JUPEDSIM_API JPS_AgentId JPS_Simulation_AddCollisionFreeSpeedModelV2Agent( JPS_CollisionFreeSpeedModelV2AgentParameters parameters, JPS_ErrorMessage* errorMessage); +/** + * Adds a new agent to the simulation. + * This can be called at any time, i.e. agents can be added at any iteration. + * NOTE: Currently there is no checking done to ensure the agent can be placed at the desired + * location. + * @param handle to the simulation to act on + * @param parameters describing the new agent. + * @param[out] errorMessage if not NULL. Will contain address of JPS_ErrorMessage in case of an + * error. + * @return id of the new agent or 0 if the agent could not be added due to an error. + */ +JUPEDSIM_API JPS_AgentId JPS_Simulation_AddCollisionFreeSpeedModelV3Agent( + JPS_Simulation handle, + JPS_CollisionFreeSpeedModelV3AgentParameters parameters, + JPS_ErrorMessage* errorMessage); + + /** * Adds a new agent to the simulation. * This can be called at any time, i.e. agents can be added at any iteration. diff --git a/libjupedsim/include/jupedsim/types.h b/libjupedsim/include/jupedsim/types.h index df82e4371..5614a5aa8 100644 --- a/libjupedsim/include/jupedsim/types.h +++ b/libjupedsim/include/jupedsim/types.h @@ -61,6 +61,7 @@ typedef enum JPS_ModelType { JPS_GeneralizedCentrifugalForceModel, JPS_CollisionFreeSpeedModel, JPS_CollisionFreeSpeedModelV2, + JPS_CollisionFreeSpeedModelV3, JPS_SocialForceModel } JPS_ModelType; diff --git a/libjupedsim/src/agent.cpp b/libjupedsim/src/agent.cpp index d09fc003f..fc56ab3a4 100644 --- a/libjupedsim/src/agent.cpp +++ b/libjupedsim/src/agent.cpp @@ -91,6 +91,8 @@ JPS_ModelType JPS_Agent_GetModelType(JPS_Agent handle) case 2: return JPS_CollisionFreeSpeedModelV2; case 3: + return JPS_CollisionFreeSpeedModelV3; + case 4: return JPS_SocialForceModel; } UNREACHABLE(); diff --git a/libjupedsim/src/collision_free_speed_model_v3.cpp b/libjupedsim/src/collision_free_speed_model_v3.cpp new file mode 100644 index 000000000..607a4ff5b --- /dev/null +++ b/libjupedsim/src/collision_free_speed_model_v3.cpp @@ -0,0 +1,169 @@ +// Copyright © 2012-2024 Forschungszentrum Jülich GmbH +// SPDX-License-Identifier: LGPL-3.0-or-later +#include "jupedsim/collision_free_speed_model.h" +#include "jupedsim/error.h" + +#include "Conversion.hpp" +#include "ErrorMessage.hpp" + +#include +#include +#include + +using jupedsim::detail::intoJPS_Point; +using jupedsim::detail::intoPoint; +using jupedsim::detail::intoTuple; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// Collision Free Speed Model V3 Builder +//////////////////////////////////////////////////////////////////////////////////////////////////// +JUPEDSIM_API JPS_CollisionFreeSpeedModelV3Builder JPS_CollisionFreeSpeedModelV3Builder_Create() +{ + return reinterpret_cast( + new CollisionFreeSpeedModelV3Builder()); +} + +JUPEDSIM_API JPS_OperationalModel JPS_CollisionFreeSpeedModelV3Builder_Build( + JPS_CollisionFreeSpeedModelV3Builder handle, + JPS_ErrorMessage* errorMessage) +{ + assert(handle != nullptr); + auto builder = reinterpret_cast(handle); + JPS_OperationalModel result{}; + try { + result = + reinterpret_cast(new CollisionFreeSpeedModelV3(builder->Build())); + } catch(const std::exception& ex) { + if(errorMessage) { + *errorMessage = reinterpret_cast(new JPS_ErrorMessage_t{ex.what()}); + } + } catch(...) { + if(errorMessage) { + *errorMessage = reinterpret_cast( + new JPS_ErrorMessage_t{"Unknown internal error."}); + } + } + return result; +} + +JUPEDSIM_API void +JPS_CollisionFreeSpeedModelV3Builder_Free(JPS_CollisionFreeSpeedModelV3Builder handle) +{ + delete reinterpret_cast(handle); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// CollisionFreeSpeedModelV3State +//////////////////////////////////////////////////////////////////////////////////////////////////// +double JPS_CollisionFreeSpeedModelV3State_GetStrengthNeighborRepulsion( + JPS_CollisionFreeSpeedModelV3State handle) +{ + assert(handle); + const auto state = reinterpret_cast(handle); + return state->strengthNeighborRepulsion; +} + +void JPS_CollisionFreeSpeedModelV3State_SetStrengthNeighborRepulsion( + JPS_CollisionFreeSpeedModelV3State handle, + double strengthNeighborRepulsion) +{ + assert(handle); + auto state = reinterpret_cast(handle); + state->strengthNeighborRepulsion = strengthNeighborRepulsion; +} + +double JPS_CollisionFreeSpeedModelV3State_GetRangeNeighborRepulsion( + JPS_CollisionFreeSpeedModelV3State handle) +{ + assert(handle); + const auto state = reinterpret_cast(handle); + return state->rangeNeighborRepulsion; +} + +void JPS_CollisionFreeSpeedModelV3State_SetRangeNeighborRepulsion( + JPS_CollisionFreeSpeedModelV3State handle, + double rangeNeighborRepulsion) +{ + assert(handle); + auto state = reinterpret_cast(handle); + state->rangeNeighborRepulsion = rangeNeighborRepulsion; +} + +double JPS_CollisionFreeSpeedModelV3State_GetStrengthGeometryRepulsion( + JPS_CollisionFreeSpeedModelV3State handle) +{ + assert(handle); + const auto state = reinterpret_cast(handle); + return state->strengthGeometryRepulsion; +} + +void JPS_CollisionFreeSpeedModelV3State_SetStrengthGeometryRepulsion( + JPS_CollisionFreeSpeedModelV3State handle, + double strengthGeometryRepulsion) +{ + assert(handle); + auto state = reinterpret_cast(handle); + state->strengthGeometryRepulsion = strengthGeometryRepulsion; +} + +double JPS_CollisionFreeSpeedModelV3State_GetRangeGeometryRepulsion( + JPS_CollisionFreeSpeedModelV3State handle) +{ + assert(handle); + const auto state = reinterpret_cast(handle); + return state->rangeNeighborRepulsion; +} + +void JPS_CollisionFreeSpeedModelV3State_SetRangeGeometryRepulsion( + JPS_CollisionFreeSpeedModelV3State handle, + double rangeNeighborRepulsion) +{ + assert(handle); + auto state = reinterpret_cast(handle); + state->rangeNeighborRepulsion = rangeNeighborRepulsion; +} + +double JPS_CollisionFreeSpeedModelV3State_GetTimeGap(JPS_CollisionFreeSpeedModelV3State handle) +{ + assert(handle); + const auto state = reinterpret_cast(handle); + return state->timeGap; +} + +void JPS_CollisionFreeSpeedModelV3State_SetTimeGap( + JPS_CollisionFreeSpeedModelV3State handle, + double time_gap) +{ + assert(handle); + auto state = reinterpret_cast(handle); + state->timeGap = time_gap; +} + +double JPS_CollisionFreeSpeedModelV3State_GetV0(JPS_CollisionFreeSpeedModelV3State handle) +{ + assert(handle); + const auto state = reinterpret_cast(handle); + return state->v0; +} + +void JPS_CollisionFreeSpeedModelV3State_SetV0(JPS_CollisionFreeSpeedModelV3State handle, double v0) +{ + assert(handle); + auto state = reinterpret_cast(handle); + state->v0 = v0; +} +double JPS_CollisionFreeSpeedModelV3State_GetRadius(JPS_CollisionFreeSpeedModelV3State handle) +{ + assert(handle); + const auto state = reinterpret_cast(handle); + return state->radius; +} + +void JPS_CollisionFreeSpeedModelV3State_SetRadius( + JPS_CollisionFreeSpeedModelV3State handle, + double radius) +{ + assert(handle); + auto state = reinterpret_cast(handle); + state->radius = radius; +} diff --git a/libjupedsim/src/simulation.cpp b/libjupedsim/src/simulation.cpp index 5c921f2c2..11ef5af0f 100644 --- a/libjupedsim/src/simulation.cpp +++ b/libjupedsim/src/simulation.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-or-later #include "jupedsim/simulation.h" +#include "OperationalModelType.hpp" #include "jupedsim/agent.h" #include "jupedsim/error.h" @@ -9,6 +10,7 @@ #include "Conversion.hpp" #include "ErrorMessage.hpp" #include "JourneyDescription.hpp" +#include "jupedsim/types.h" #include #include @@ -281,6 +283,47 @@ JPS_AgentId JPS_Simulation_AddCollisionFreeSpeedModelV2Agent( return result.getID(); } +JPS_AgentId JPS_Simulation_AddCollisionFreeSpeedModelV3Agent( + JPS_Simulation handle, + JPS_CollisionFreeSpeedModelV3AgentParameters parameters, + JPS_ErrorMessage* errorMessage) +{ + assert(handle); + auto result = GenericAgent::ID::Invalid; + auto simulation = reinterpret_cast(handle); + try { + if(simulation->ModelType() != OperationalModelType::COLLISION_FREE_SPEED_V3) { + throw std::runtime_error( + "Simulation is not configured to use Collision Free Speed Model V3"); + } + GenericAgent agent( + GenericAgent::ID::Invalid, + Journey::ID(parameters.journeyId), + BaseStage::ID(parameters.stageId), + intoPoint(parameters.position), + {}, + CollisionFreeSpeedModelV3Data{ + parameters.strengthNeighborRepulsion, + parameters.rangeNeighborRepulsion, + parameters.strengthGeometryRepulsion, + parameters.rangeGeometryRepulsion, + parameters.time_gap, + parameters.v0, + parameters.radius}); + result = simulation->AddAgent(std::move(agent)); + } catch(const std::exception& ex) { + if(errorMessage) { + *errorMessage = reinterpret_cast(new JPS_ErrorMessage_t{ex.what()}); + } + } catch(...) { + if(errorMessage) { + *errorMessage = reinterpret_cast( + new JPS_ErrorMessage_t{"Unknown internal error."}); + } + } + return result.getID(); +} + JPS_AgentId JPS_Simulation_AddSocialForceModelAgent( JPS_Simulation handle, JPS_SocialForceModelAgentParameters parameters, @@ -475,6 +518,8 @@ JPS_ModelType JPS_Simulation_ModelType(JPS_Simulation handle) return JPS_GeneralizedCentrifugalForceModel; case OperationalModelType::COLLISION_FREE_SPEED_V2: return JPS_CollisionFreeSpeedModelV2; + case OperationalModelType::COLLISION_FREE_SPEED_V3: + return JPS_CollisionFreeSpeedModelV3; case OperationalModelType::SOCIAL_FORCE: return JPS_SocialForceModel; } diff --git a/libsimulator/CMakeLists.txt b/libsimulator/CMakeLists.txt index 32b1db611..ce121f816 100644 --- a/libsimulator/CMakeLists.txt +++ b/libsimulator/CMakeLists.txt @@ -12,12 +12,18 @@ add_library(simulator STATIC src/CollisionFreeSpeedModelBuilder.hpp src/CollisionFreeSpeedModelData.hpp src/CollisionFreeSpeedModelUpdate.hpp - src/CollisionFreeSpeedModelV2.cpp + src/CollisionFreeSpeedModelV2.cpp src/CollisionFreeSpeedModelV2.hpp src/CollisionFreeSpeedModelV2Builder.cpp src/CollisionFreeSpeedModelV2Builder.hpp src/CollisionFreeSpeedModelV2Data.hpp src/CollisionFreeSpeedModelV2Update.hpp + src/CollisionFreeSpeedModelV3.cpp + src/CollisionFreeSpeedModelV3.hpp + src/CollisionFreeSpeedModelV3Builder.cpp + src/CollisionFreeSpeedModelV3Builder.hpp + src/CollisionFreeSpeedModelV3Data.hpp + src/CollisionFreeSpeedModelV3Update.hpp src/CollisionGeometry.cpp src/CollisionGeometry.hpp src/Ellipse.cpp diff --git a/libsimulator/src/CollisionFreeSpeedModelV3.cpp b/libsimulator/src/CollisionFreeSpeedModelV3.cpp new file mode 100644 index 000000000..1990b390e --- /dev/null +++ b/libsimulator/src/CollisionFreeSpeedModelV3.cpp @@ -0,0 +1,231 @@ +// Copyright © 2012-2024 Forschungszentrum Jülich GmbH +// SPDX-License-Identifier: LGPL-3.0-or-later +#include "CollisionFreeSpeedModelV3.hpp" +#include +#include "CollisionFreeSpeedModelV3Data.hpp" +#include "CollisionFreeSpeedModelV3Update.hpp" +#include "GenericAgent.hpp" +#include "GeometricFunctions.hpp" +#include "Logger.hpp" +#include "Mathematics.hpp" +#include "NeighborhoodSearch.hpp" +#include "OperationalModel.hpp" +#include "SimulationError.hpp" +#include "Stage.hpp" + +#include +#include +#include +#include +#include + +OperationalModelType CollisionFreeSpeedModelV3::Type() const +{ + return OperationalModelType::COLLISION_FREE_SPEED_V3; +} + +OperationalModelUpdate CollisionFreeSpeedModelV3::ComputeNewPosition( + double dT, + const GenericAgent& ped, + const CollisionGeometry& geometry, + const NeighborhoodSearchType& neighborhoodSearch) const +{ + auto neighborhood = neighborhoodSearch.GetNeighboringAgents(ped.pos, _cutOffRadius); + const auto& boundary = geometry.LineSegmentsInApproxDistanceTo(ped.pos); + + // Remove any agent from the neighborhood that is obstructed by geometry and the current + // agent + neighborhood.erase( + std::remove_if( + std::begin(neighborhood), + std::end(neighborhood), + [&ped, &boundary](const auto& neighbor) { + if(ped.id == neighbor.id) { + return true; + } + const auto agent_to_neighbor = LineSegment(ped.pos, neighbor.pos); + if(std::find_if( + boundary.cbegin(), + boundary.cend(), + [&agent_to_neighbor](const auto& boundary_segment) { + return intersects(agent_to_neighbor, boundary_segment); + }) != boundary.end()) { + return true; + } + + return false; + }), + std::end(neighborhood)); + + const auto neighborRepulsion = std::accumulate( + std::begin(neighborhood), + std::end(neighborhood), + Point{}, + [&ped, this](const auto& res, const auto& neighbor) { + return res + NeighborRepulsion(ped, neighbor); + }); + + const auto boundaryRepulsion = std::accumulate( + boundary.cbegin(), + boundary.cend(), + Point(0, 0), + [this, &ped](const auto& acc, const auto& element) { + return acc + BoundaryRepulsion(ped, element); + }); + + const auto desired_direction = (ped.destination - ped.pos).Normalized(); + auto direction = (desired_direction + neighborRepulsion + boundaryRepulsion).Normalized(); + if(direction == Point{}) { + direction = ped.orientation; + } + const auto spacing = std::accumulate( + std::begin(neighborhood), + std::end(neighborhood), + std::numeric_limits::max(), + [&ped, &direction, this](const auto& res, const auto& neighbor) { + return std::min(res, GetSpacing(ped, neighbor, direction)); + }); + + const auto& model = std::get(ped.model); + const auto optimal_speed = OptimalSpeed(ped, spacing, model.timeGap); + const auto velocity = direction * optimal_speed; + return CollisionFreeSpeedModelV3Update{ped.pos + velocity * dT, direction}; +}; + +void CollisionFreeSpeedModelV3::ApplyUpdate(const OperationalModelUpdate& upd, GenericAgent& agent) + const +{ + const auto& update = std::get(upd); + agent.pos = update.position; + agent.orientation = update.orientation; +} + +void CollisionFreeSpeedModelV3::CheckModelConstraint( + const GenericAgent& agent, + const NeighborhoodSearchType& neighborhoodSearch, + const CollisionGeometry& geometry) const +{ + const auto& model = std::get(agent.model); + + const auto r = model.radius; + constexpr double rMin = 0.; + constexpr double rMax = 2.; + validateConstraint(r, rMin, rMax, "radius", true); + + const auto v0 = model.v0; + constexpr double v0Min = 0.; + constexpr double v0Max = 10.; + validateConstraint(v0, v0Min, v0Max, "v0"); + + const auto timeGap = model.timeGap; + constexpr double timeGapMin = 0.1; + constexpr double timeGapMax = 10.; + validateConstraint(timeGap, timeGapMin, timeGapMax, "timeGap"); + + const auto neighbors = neighborhoodSearch.GetNeighboringAgents(agent.pos, 2); + for(const auto& neighbor : neighbors) { + if(agent.id == neighbor.id) { + continue; + } + const auto& neighbor_model = std::get(neighbor.model); + const auto contanctdDist = r + neighbor_model.radius; + const auto distance = (agent.pos - neighbor.pos).Norm(); + if(contanctdDist >= distance) { + throw SimulationError( + "Model constraint violation: Agent {} too close to agent {}: distance {}", + agent.pos, + neighbor.pos, + distance); + } + } + + const auto lineSegments = geometry.LineSegmentsInDistanceTo(r, agent.pos); + if(std::begin(lineSegments) != std::end(lineSegments)) { + throw SimulationError( + "Model constraint violation: Agent {} too close to geometry boundaries, distance " + "<= {}", + agent.pos, + r); + } +} + +std::unique_ptr CollisionFreeSpeedModelV3::Clone() const +{ + return std::make_unique(*this); +} + +double CollisionFreeSpeedModelV3::OptimalSpeed( + const GenericAgent& ped, + double spacing, + double time_gap) const +{ + const auto& model = std::get(ped.model); + double min_spacing = -0.05; + return std::min(std::max(spacing / time_gap, min_spacing + ), model.v0); +} + +double CollisionFreeSpeedModelV3::GetSpacing( + const GenericAgent& ped1, + const GenericAgent& ped2, + const Point& direction) const +{ + const auto& model1 = std::get(ped1.model); + const auto& model2 = std::get(ped2.model); + const auto distp12 = ped2.pos - ped1.pos; + const auto inFront = direction.ScalarProduct(distp12) >= 0; + if(!inFront) { + return std::numeric_limits::max(); + } + + const auto left = direction.Rotate90Deg(); + const auto l = model1.radius + model2.radius; + //std::cout << ped1.id.getID() << ": r="<< model1.radius << ", r=" << model2.radius << "\n"; // + //std::cout << ped1.pos.x << " - " << ped2.pos.x << "\n"; + float min_dist = l + 0.5;// TODO + bool inCorridor = std::abs(left.ScalarProduct(distp12)) <= l; + if(!inCorridor) { + return std::numeric_limits::max(); + } + return distp12.Norm() - min_dist; +} +Point CollisionFreeSpeedModelV3::NeighborRepulsion( + const GenericAgent& ped1, + const GenericAgent& ped2) const +{ + const auto distp12 = ped2.pos - ped1.pos; + const auto [distance, direction] = distp12.NormAndNormalized(); + const auto& model1 = std::get(ped1.model); + const auto& model2 = std::get(ped2.model); + + const auto l = model1.radius + model2.radius; + double seed = 42; + static std::random_device rd; + static std::mt19937 gen(seed); + std::uniform_real_distribution<> dis(-0.1, 0.1); // Small random values + + Point randomVec(dis(gen), dis(gen)); + + auto randomizedDirection = (direction + randomVec).Normalized(); + return randomizedDirection * -(model1.strengthNeighborRepulsion * + exp((l - distance) / model1.rangeNeighborRepulsion)); + + + + // return direction * -(model1.strengthNeighborRepulsion * + // exp((l - distance) / model1.rangeNeighborRepulsion)); +} + +Point CollisionFreeSpeedModelV3::BoundaryRepulsion( + const GenericAgent& ped, + const LineSegment& boundary_segment) const +{ + const auto pt = boundary_segment.ShortestPoint(ped.pos); + const auto dist_vec = pt - ped.pos; + const auto [dist, e_iw] = dist_vec.NormAndNormalized(); + const auto& model = std::get(ped.model); + const auto l = model.radius; + const auto R_iw = + -model.strengthGeometryRepulsion * exp((l - dist) / model.rangeGeometryRepulsion); + return e_iw * R_iw; +} diff --git a/libsimulator/src/CollisionFreeSpeedModelV3.hpp b/libsimulator/src/CollisionFreeSpeedModelV3.hpp new file mode 100644 index 000000000..6f84d4173 --- /dev/null +++ b/libsimulator/src/CollisionFreeSpeedModelV3.hpp @@ -0,0 +1,43 @@ +// Copyright © 2012-2024 Forschungszentrum Jülich GmbH +// SPDX-License-Identifier: LGPL-3.0-or-later +#pragma once + +#include "CollisionFreeSpeedModelV3Data.hpp" +#include "CollisionGeometry.hpp" +#include "NeighborhoodSearch.hpp" +#include "OperationalModel.hpp" +#include "UniqueID.hpp" + +struct GenericAgent; + +class CollisionFreeSpeedModelV3 : public OperationalModel +{ +public: + using NeighborhoodSearchType = NeighborhoodSearch; + +private: + double _cutOffRadius{3}; + +public: + CollisionFreeSpeedModelV3() = default; + ~CollisionFreeSpeedModelV3() override = default; + OperationalModelType Type() const override; + OperationalModelUpdate ComputeNewPosition( + double dT, + const GenericAgent& ped, + const CollisionGeometry& geometry, + const NeighborhoodSearchType& neighborhoodSearch) const override; + void ApplyUpdate(const OperationalModelUpdate& update, GenericAgent& agent) const override; + void CheckModelConstraint( + const GenericAgent& agent, + const NeighborhoodSearchType& neighborhoodSearch, + const CollisionGeometry& geometry) const override; + std::unique_ptr Clone() const override; + +private: + double OptimalSpeed(const GenericAgent& ped, double spacing, double time_gap) const; + double + GetSpacing(const GenericAgent& ped1, const GenericAgent& ped2, const Point& direction) const; + Point NeighborRepulsion(const GenericAgent& ped1, const GenericAgent& ped2) const; + Point BoundaryRepulsion(const GenericAgent& ped, const LineSegment& boundary_segment) const; +}; diff --git a/libsimulator/src/CollisionFreeSpeedModelV3Builder.cpp b/libsimulator/src/CollisionFreeSpeedModelV3Builder.cpp new file mode 100644 index 000000000..5d2b9d4e1 --- /dev/null +++ b/libsimulator/src/CollisionFreeSpeedModelV3Builder.cpp @@ -0,0 +1,12 @@ +// Copyright © 2012-2024 Forschungszentrum Jülich GmbH +// SPDX-License-Identifier: LGPL-3.0-or-later +#include "CollisionFreeSpeedModelV3Builder.hpp" + +CollisionFreeSpeedModelV3Builder::CollisionFreeSpeedModelV3Builder() +{ +} + +CollisionFreeSpeedModelV3 CollisionFreeSpeedModelV3Builder::Build() +{ + return CollisionFreeSpeedModelV3(); +} diff --git a/libsimulator/src/CollisionFreeSpeedModelV3Builder.hpp b/libsimulator/src/CollisionFreeSpeedModelV3Builder.hpp new file mode 100644 index 000000000..7de825f0a --- /dev/null +++ b/libsimulator/src/CollisionFreeSpeedModelV3Builder.hpp @@ -0,0 +1,11 @@ +// Copyright © 2012-2024 Forschungszentrum Jülich GmbH +// SPDX-License-Identifier: LGPL-3.0-or-later +#pragma once + +#include "CollisionFreeSpeedModelV3.hpp" +class CollisionFreeSpeedModelV3Builder +{ +public: + CollisionFreeSpeedModelV3Builder(); + CollisionFreeSpeedModelV3 Build(); +}; diff --git a/libsimulator/src/CollisionFreeSpeedModelV3Data.hpp b/libsimulator/src/CollisionFreeSpeedModelV3Data.hpp new file mode 100644 index 000000000..5ab5aaf19 --- /dev/null +++ b/libsimulator/src/CollisionFreeSpeedModelV3Data.hpp @@ -0,0 +1,39 @@ +// Copyright © 2012-2024 Forschungszentrum Jülich GmbH +// SPDX-License-Identifier: LGPL-3.0-or-later +#pragma once + +#include "Point.hpp" + +struct CollisionFreeSpeedModelV3Data { + double strengthNeighborRepulsion{}; + double rangeNeighborRepulsion{}; + double strengthGeometryRepulsion{}; + double rangeGeometryRepulsion{}; + + double timeGap{1}; + double v0{1.2}; + double radius{0.15}; +}; + +template <> +struct fmt::formatter { + + constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } + + template + auto format(const CollisionFreeSpeedModelV3Data& m, FormatContext& ctx) const + { + return fmt::format_to( + ctx.out(), + "CollisionFreeSpeedModelV3[strengthNeighborRepulsion={}, " + "rangeNeighborRepulsion={}, strengthGeometryRepulsion={}, rangeGeometryRepulsion={}, " + "timeGap={}, v0={}, radius={}])", + m.strengthNeighborRepulsion, + m.rangeNeighborRepulsion, + m.strengthGeometryRepulsion, + m.rangeGeometryRepulsion, + m.timeGap, + m.v0, + m.radius); + } +}; diff --git a/libsimulator/src/CollisionFreeSpeedModelV3Update.hpp b/libsimulator/src/CollisionFreeSpeedModelV3Update.hpp new file mode 100644 index 000000000..3eafb2aa3 --- /dev/null +++ b/libsimulator/src/CollisionFreeSpeedModelV3Update.hpp @@ -0,0 +1,9 @@ +// Copyright © 2012-2024 Forschungszentrum Jülich GmbH +// SPDX-License-Identifier: LGPL-3.0-or-later +#pragma once +#include "Point.hpp" + +struct CollisionFreeSpeedModelV3Update { + Point position{}; + Point orientation{}; +}; diff --git a/libsimulator/src/GenericAgent.hpp b/libsimulator/src/GenericAgent.hpp index c53f38aa0..61faf19c9 100644 --- a/libsimulator/src/GenericAgent.hpp +++ b/libsimulator/src/GenericAgent.hpp @@ -3,6 +3,7 @@ #pragma once #include "CollisionFreeSpeedModelData.hpp" #include "CollisionFreeSpeedModelV2Data.hpp" +#include "CollisionFreeSpeedModelV3Data.hpp" #include "GeneralizedCentrifugalForceModelData.hpp" #include "OperationalModel.hpp" #include "Point.hpp" @@ -33,6 +34,7 @@ struct GenericAgent { GeneralizedCentrifugalForceModelData, CollisionFreeSpeedModelData, CollisionFreeSpeedModelV2Data, + CollisionFreeSpeedModelV3Data, SocialForceModelData>; Model model{}; diff --git a/libsimulator/src/OperationalModelType.hpp b/libsimulator/src/OperationalModelType.hpp index d75568247..e85e45099 100644 --- a/libsimulator/src/OperationalModelType.hpp +++ b/libsimulator/src/OperationalModelType.hpp @@ -6,5 +6,6 @@ enum class OperationalModelType { COLLISION_FREE_SPEED, GENERALIZED_CENTRIFUGAL_FORCE, COLLISION_FREE_SPEED_V2, + COLLISION_FREE_SPEED_V3, SOCIAL_FORCE }; diff --git a/libsimulator/src/OperationalModelUpdate.hpp b/libsimulator/src/OperationalModelUpdate.hpp index 19d1368b4..ecedffc13 100644 --- a/libsimulator/src/OperationalModelUpdate.hpp +++ b/libsimulator/src/OperationalModelUpdate.hpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-or-later #include "CollisionFreeSpeedModelUpdate.hpp" #include "CollisionFreeSpeedModelV2Update.hpp" +#include "CollisionFreeSpeedModelV3Update.hpp" #include "GeneralizedCentrifugalForceModelUpdate.hpp" #include "SocialForceModelUpdate.hpp" @@ -11,4 +12,5 @@ using OperationalModelUpdate = std::variant< GeneralizedCentrifugalForceModelUpdate, CollisionFreeSpeedModelUpdate, CollisionFreeSpeedModelV2Update, + CollisionFreeSpeedModelV3Update, SocialForceModelUpdate>; diff --git a/python_bindings_jupedsim/CMakeLists.txt b/python_bindings_jupedsim/CMakeLists.txt index fe65c0b9a..288a70039 100644 --- a/python_bindings_jupedsim/CMakeLists.txt +++ b/python_bindings_jupedsim/CMakeLists.txt @@ -6,6 +6,7 @@ add_library(py_jupedsim MODULE generalized_centrifugal_force_model.cpp collision_free_speed_model.cpp collision_free_speed_model_v2.cpp + collision_free_speed_model_v3.cpp social_force_model.cpp logging.cpp logging.hpp diff --git a/python_bindings_jupedsim/agent.cpp b/python_bindings_jupedsim/agent.cpp index c3919f955..95c36ac6f 100644 --- a/python_bindings_jupedsim/agent.cpp +++ b/python_bindings_jupedsim/agent.cpp @@ -70,6 +70,7 @@ void init_agent(py::module_& m) std::unique_ptr, std::unique_ptr, std::unique_ptr, + std::unique_ptr, std::unique_ptr> { switch(JPS_Agent_GetModelType(w.handle)) { case JPS_GeneralizedCentrifugalForceModel: @@ -81,6 +82,9 @@ void init_agent(py::module_& m) case JPS_CollisionFreeSpeedModelV2: return std::make_unique( JPS_Agent_GetCollisionFreeSpeedModelV2State(w.handle, nullptr)); + case JPS_CollisionFreeSpeedModelV3: + return std::make_unique( + JPS_Agent_GetCollisionFreeSpeedModelV3State(w.handle, nullptr)); case JPS_SocialForceModel: return std::make_unique( JPS_Agent_GetSocialForceModelState(w.handle, nullptr)); diff --git a/python_bindings_jupedsim/bindings_jupedsim.cpp b/python_bindings_jupedsim/bindings_jupedsim.cpp index 054cfe13b..3784ef6d6 100644 --- a/python_bindings_jupedsim/bindings_jupedsim.cpp +++ b/python_bindings_jupedsim/bindings_jupedsim.cpp @@ -10,6 +10,7 @@ void init_trace(py::module_& m); void init_generalized_centrifugal_force_model(py::module_& m); void init_collision_free_speed_model(py::module_& m); void init_collision_free_speed_model_v2(py::module_& m); +void init_collision_free_speed_model_v3(py::module_& m); void init_social_force_model(py::module_& m); void init_geometry(py::module_& m); void init_routing(py::module_& m); @@ -27,6 +28,7 @@ PYBIND11_MODULE(py_jupedsim, m) init_generalized_centrifugal_force_model(m); init_collision_free_speed_model(m); init_collision_free_speed_model_v2(m); + init_collision_free_speed_model_v3(m); init_social_force_model(m); init_geometry(m); init_routing(m); diff --git a/python_bindings_jupedsim/collision_free_speed_model_v3.cpp b/python_bindings_jupedsim/collision_free_speed_model_v3.cpp new file mode 100644 index 000000000..f81a8834f --- /dev/null +++ b/python_bindings_jupedsim/collision_free_speed_model_v3.cpp @@ -0,0 +1,147 @@ +// Copyright © 2012-2024 Forschungszentrum Jülich GmbH +// SPDX-License-Identifier: LGPL-3.0-or-later +#include "jupedsim/collision_free_speed_model_v3.h" +#include "conversion.hpp" +#include "wrapper.hpp" + +#include + +#include +#include +#include +#include + +namespace py = pybind11; + +void init_collision_free_speed_model_v3(py::module_& m) +{ + py::class_( + m, "CollisionFreeSpeedModelV3AgentParameters") + .def( + py::init([](std::tuple position, + double time_gap, + double v0, + double radius, + JPS_JourneyId journey_id, + JPS_StageId stage_id, + double strengthNeighborRepulsion, + double rangeNeighborRepulsion, + double strengthGeometryRepulsion, + double rangeGeometryRepulsion) { + return JPS_CollisionFreeSpeedModelV3AgentParameters{ + intoJPS_Point(position), + journey_id, + stage_id, + time_gap, + v0, + radius, + strengthNeighborRepulsion, + rangeNeighborRepulsion, + strengthGeometryRepulsion, + rangeGeometryRepulsion}; + }), + py::kw_only(), + py::arg("position"), + py::arg("time_gap"), + py::arg("v0"), + py::arg("radius"), + py::arg("journey_id"), + py::arg("stage_id"), + py::arg("strength_neighbor_repulsion"), + py::arg("range_neighbor_repulsion"), + py::arg("strength_geometry_repulsion"), + py::arg("range_geometry_repulsion")) + .def("__repr__", [](const JPS_CollisionFreeSpeedModelV3AgentParameters& p) { + return fmt::format( + "position: {}, journey_id: {}, stage_id: {}, " + "time_gap: {}, v0: {}, radius: {}", + "strength_neighbor_repulsion: {}, range_neighbor_repulsion: {}" + "strength_geometry_repulsion: {}, range_geometry_repulsion: {}", + intoTuple(p.position), + p.journeyId, + p.stageId, + p.time_gap, + p.v0, + p.radius, + p.strengthNeighborRepulsion, + p.rangeNeighborRepulsion, + p.strengthGeometryRepulsion, + p.rangeGeometryRepulsion); + }); + py::class_(m, "CollisionFreeSpeedModelV3Builder") + .def(py::init([]() { + return std::make_unique( + JPS_CollisionFreeSpeedModelV3Builder_Create()); + })) + .def("build", [](JPS_CollisionFreeSpeedModelV3Builder_Wrapper& w) { + JPS_ErrorMessage errorMsg{}; + auto result = JPS_CollisionFreeSpeedModelV3Builder_Build(w.handle, &errorMsg); + if(result) { + return std::make_unique(result); + } + auto msg = std::string(JPS_ErrorMessage_GetMessage(errorMsg)); + JPS_ErrorMessage_Free(errorMsg); + throw std::runtime_error{msg}; + }); + py::class_(m, "CollisionFreeSpeedModelV3State") + .def_property( + "time_gap", + [](const JPS_CollisionFreeSpeedModelV3State_Wrapper& w) { + return JPS_CollisionFreeSpeedModelV3State_GetTimeGap(w.handle); + }, + [](JPS_CollisionFreeSpeedModelV3State_Wrapper& w, double time_gap) { + JPS_CollisionFreeSpeedModelV3State_SetTimeGap(w.handle, time_gap); + }) + .def_property( + "v0", + [](const JPS_CollisionFreeSpeedModelV3State_Wrapper& w) { + return JPS_CollisionFreeSpeedModelV3State_GetV0(w.handle); + }, + [](JPS_CollisionFreeSpeedModelV3State_Wrapper& w, double v0) { + JPS_CollisionFreeSpeedModelV3State_SetV0(w.handle, v0); + }) + .def_property( + "radius", + [](const JPS_CollisionFreeSpeedModelV3State_Wrapper& w) { + return JPS_CollisionFreeSpeedModelV3State_GetRadius(w.handle); + }, + [](JPS_CollisionFreeSpeedModelV3State_Wrapper& w, double radius) { + JPS_CollisionFreeSpeedModelV3State_SetRadius(w.handle, radius); + }) + .def_property( + "strength_neighbor_repulsion", + [](const JPS_CollisionFreeSpeedModelV3State_Wrapper& w) { + return JPS_CollisionFreeSpeedModelV3State_GetStrengthNeighborRepulsion(w.handle); + }, + [](JPS_CollisionFreeSpeedModelV3State_Wrapper& w, double strengthNeighborRepulsion) { + JPS_CollisionFreeSpeedModelV3State_SetStrengthNeighborRepulsion( + w.handle, strengthNeighborRepulsion); + }) + .def_property( + "range_neighbor_repulsion", + [](const JPS_CollisionFreeSpeedModelV3State_Wrapper& w) { + return JPS_CollisionFreeSpeedModelV3State_GetRangeNeighborRepulsion(w.handle); + }, + [](JPS_CollisionFreeSpeedModelV3State_Wrapper& w, double rangeNeighborRepulsion) { + JPS_CollisionFreeSpeedModelV3State_SetRangeNeighborRepulsion( + w.handle, rangeNeighborRepulsion); + }) + .def_property( + "strength_geometry_repulsion", + [](const JPS_CollisionFreeSpeedModelV3State_Wrapper& w) { + return JPS_CollisionFreeSpeedModelV3State_GetStrengthGeometryRepulsion(w.handle); + }, + [](JPS_CollisionFreeSpeedModelV3State_Wrapper& w, double strengthGeometryRepulsion) { + JPS_CollisionFreeSpeedModelV3State_SetStrengthGeometryRepulsion( + w.handle, strengthGeometryRepulsion); + }) + .def_property( + "range_geometry_repulsion", + [](const JPS_CollisionFreeSpeedModelV3State_Wrapper& w) { + return JPS_CollisionFreeSpeedModelV3State_GetRangeGeometryRepulsion(w.handle); + }, + [](JPS_CollisionFreeSpeedModelV3State_Wrapper& w, double rangeGeometryRepulsion) { + JPS_CollisionFreeSpeedModelV3State_SetRangeGeometryRepulsion( + w.handle, rangeGeometryRepulsion); + }); +} diff --git a/python_bindings_jupedsim/simulation.cpp b/python_bindings_jupedsim/simulation.cpp index 5c4901d3b..39075c505 100644 --- a/python_bindings_jupedsim/simulation.cpp +++ b/python_bindings_jupedsim/simulation.cpp @@ -156,6 +156,20 @@ void init_simulation(py::module_& m) JPS_ErrorMessage_Free(errorMsg); throw std::runtime_error{msg}; }) + .def( + "add_agent", + [](JPS_Simulation_Wrapper& simulation, + JPS_CollisionFreeSpeedModelV3AgentParameters& parameters) { + JPS_ErrorMessage errorMsg{}; + auto result = JPS_Simulation_AddCollisionFreeSpeedModelV3Agent( + simulation.handle, parameters, &errorMsg); + if(result) { + return result; + } + auto msg = std::string(JPS_ErrorMessage_GetMessage(errorMsg)); + JPS_ErrorMessage_Free(errorMsg); + throw std::runtime_error{msg}; + }) .def( "add_agent", [](JPS_Simulation_Wrapper& simulation, diff --git a/python_bindings_jupedsim/wrapper.hpp b/python_bindings_jupedsim/wrapper.hpp index e03749677..9e88ff3af 100644 --- a/python_bindings_jupedsim/wrapper.hpp +++ b/python_bindings_jupedsim/wrapper.hpp @@ -38,6 +38,7 @@ OWNED_WRAPPER(JPS_GeometryBuilder); OWNED_WRAPPER(JPS_OperationalModel); OWNED_WRAPPER(JPS_CollisionFreeSpeedModelBuilder); OWNED_WRAPPER(JPS_CollisionFreeSpeedModelV2Builder); +OWNED_WRAPPER(JPS_CollisionFreeSpeedModelV3Builder); OWNED_WRAPPER(JPS_GeneralizedCentrifugalForceModelBuilder); OWNED_WRAPPER(JPS_SocialForceModelBuilder); OWNED_WRAPPER(JPS_JourneyDescription); @@ -55,4 +56,5 @@ WRAPPER(JPS_Agent); WRAPPER(JPS_GeneralizedCentrifugalForceModelState); WRAPPER(JPS_CollisionFreeSpeedModelState); WRAPPER(JPS_CollisionFreeSpeedModelV2State); +WRAPPER(JPS_CollisionFreeSpeedModelV3State); WRAPPER(JPS_SocialForceModelState); diff --git a/python_modules/jupedsim/jupedsim/__init__.py b/python_modules/jupedsim/jupedsim/__init__.py index b923adefe..d313a39de 100644 --- a/python_modules/jupedsim/jupedsim/__init__.py +++ b/python_modules/jupedsim/jupedsim/__init__.py @@ -35,6 +35,12 @@ CollisionFreeSpeedModelV2AgentParameters, CollisionFreeSpeedModelV2State, ) +from jupedsim.models.collision_free_speed_v3 import ( + CollisionFreeSpeedModelV3, + CollisionFreeSpeedModelV3AgentParameters, + CollisionFreeSpeedModelV3State, +) + from jupedsim.models.generalized_centrifugal_force import ( GeneralizedCentrifugalForceModel, GeneralizedCentrifugalForceModelAgentParameters, @@ -105,6 +111,9 @@ "CollisionFreeSpeedModelV2AgentParameters", "CollisionFreeSpeedModelV2", "CollisionFreeSpeedModelV2State", + "CollisionFreeSpeedModelV3AgentParameters", + "CollisionFreeSpeedModelV3", + "CollisionFreeSpeedModelV3State", "SocialForceModelAgentParameters", "SocialForceModel", "SocialForceModelState", diff --git a/python_modules/jupedsim/jupedsim/agent.py b/python_modules/jupedsim/jupedsim/agent.py index 9623e58ef..136731cba 100644 --- a/python_modules/jupedsim/jupedsim/agent.py +++ b/python_modules/jupedsim/jupedsim/agent.py @@ -6,6 +6,9 @@ from jupedsim.models.collision_free_speed_v2 import ( CollisionFreeSpeedModelV2State, ) +from jupedsim.models.collision_free_speed_v3 import ( + CollisionFreeSpeedModelV3State, +) from jupedsim.models.generalized_centrifugal_force import ( GeneralizedCentrifugalForceModelState, ) @@ -115,6 +118,8 @@ def model( return CollisionFreeSpeedModelState(model) elif isinstance(model, py_jps.CollisionFreeSpeedModelV2State): return CollisionFreeSpeedModelV2State(model) + elif isinstance(model, py_jps.CollisionFreeSpeedModelV3State): + return CollisionFreeSpeedModelV3State(model) elif isinstance(model, py_jps.SocialForceModelState): return SocialForceModelState(model) else: diff --git a/python_modules/jupedsim/jupedsim/models/collision_free_speed_v3.py b/python_modules/jupedsim/jupedsim/models/collision_free_speed_v3.py new file mode 100644 index 000000000..fc1688976 --- /dev/null +++ b/python_modules/jupedsim/jupedsim/models/collision_free_speed_v3.py @@ -0,0 +1,153 @@ +# Copyright © 2012-2024 Forschungszentrum Jülich GmbH +# SPDX-License-Identifier: LGPL-3.0-or-later + +from dataclasses import dataclass + +import jupedsim.native as py_jps + + +@dataclass(kw_only=True) +class CollisionFreeSpeedModelV3: + """Collision Free Speed Model V3 + + This is a variation of the Collision Free Speed Model where geometry and neighbor repulsion are individual + agent parameters instead of global parameters. + + A general description of the Collision Free Speed Model can be found in the originating publication + https://arxiv.org/abs/1512.05597 + + A more detailed description can be found at https://pedestriandynamics.org/models/collision_free_speed_model/ + """ + + pass + + +@dataclass(kw_only=True) +class CollisionFreeSpeedModelV3AgentParameters: + """ + Agent parameters for Collision Free Speed Model V3. + + See the scientific publication for more details about this model + https://arxiv.org/abs/1512.05597 + + .. note:: + + Instances of this type are copied when creating the agent, you can safely + create one instance of this type and modify it between calls to `add_agent` + + E.g.: + + .. code:: python + + positions = [...] # List of initial agent positions + params = CollisionFreeSpeedModelV3AgentParameters(v0=0.9) # all agents are slower + for p in positions: + params.position = p + sim.add_agent(params) + + Attributes: + position: Position of the agent. + time_gap: Time constant that describe how fast pedestrian close gaps. + v0: Maximum speed of the agent. + radius: Radius of the agent. + journey_id: Id of the journey the agent follows. + stage_id: Id of the stage the agent targets. + strength_neighbor_repulsion: Strength of the repulsion from neighbors + range_neighbor_repulsion: Range of the repulsion from neighbors + strength_geometry_repulsion: Strength of the repulsion from geometry boundaries + range_geometry_repulsion: Range of the repulsion from geometry boundaries + """ + + position: tuple[float, float] = (0.0, 0.0) + time_gap: float = 1.0 + v0: float = 1.2 + radius: float = 0.2 + journey_id: int = 0 + stage_id: int = 0 + strength_neighbor_repulsion: float = 8.0 + range_neighbor_repulsion: float = 0.1 + strength_geometry_repulsion: float = 5.0 + range_geometry_repulsion: float = 0.02 + + def as_native( + self, + ) -> py_jps.CollisionFreeSpeedModelV3AgentParameters: + return py_jps.CollisionFreeSpeedModelV3AgentParameters( + position=self.position, + time_gap=self.time_gap, + v0=self.v0, + radius=self.radius, + journey_id=self.journey_id, + stage_id=self.stage_id, + strength_neighbor_repulsion=self.strength_neighbor_repulsion, + range_neighbor_repulsion=self.range_neighbor_repulsion, + strength_geometry_repulsion=self.strength_geometry_repulsion, + range_geometry_repulsion=self.range_geometry_repulsion, + ) + + +class CollisionFreeSpeedModelV3State: + def __init__(self, backing): + self._obj = backing + + @property + def time_gap(self) -> float: + return self._obj.time_gap + + @time_gap.setter + def time_gap(self, time_gap): + self._obj.time_gap = time_gap + + @property + def v0(self) -> float: + """Maximum speed of this agent.""" + return self._obj.v0 + + @v0.setter + def v0(self, v0): + self._obj.v0 = v0 + + @property + def radius(self) -> float: + """Radius of this agent.""" + return self._obj.radius + + @radius.setter + def radius(self, radius): + self._obj.radius = radius + + @property + def strength_neighbor_repulsion(self) -> float: + """Strength of the repulsion from neighbors of this agent.""" + return self._obj.strength_neighbor_repulsion + + @strength_neighbor_repulsion.setter + def strength_neighbor_repulsion(self, strength_neighbor_repulsion): + self._obj.strength_neighbor_repulsion = strength_neighbor_repulsion + + @property + def range_neighbor_repulsion(self) -> float: + """Range of the repulsion from neighbors of this agent.""" + return self._obj.range_neighbor_repulsion + + @range_neighbor_repulsion.setter + def range_neighbor_repulsion(self, range_neighbor_repulsion): + self._obj.range_neighbor_repulsion = range_neighbor_repulsion + + @property + def strength_geometry_repulsion(self) -> float: + """Strength of the repulsion from geometry boundaries of this agent.""" + return self._obj.strength_geometry_repulsion + + @strength_geometry_repulsion.setter + def strength_geometry_repulsion(self, strength_geometry_repulsion): + self._obj.strength_geometry_repulsion = strength_geometry_repulsion + + @property + def range_geometry_repulsion(self) -> float: + """Range of the repulsion from geometry boundaries of this agent.""" + return self._obj.range_geometry_repulsion + + @range_geometry_repulsion.setter + def range_geometry_repulsion(self, range_geometry_repulsion): + self._obj.range_geometry_repulsion = range_geometry_repulsion diff --git a/python_modules/jupedsim/jupedsim/simulation.py b/python_modules/jupedsim/jupedsim/simulation.py index cf61544a5..ddb9415db 100644 --- a/python_modules/jupedsim/jupedsim/simulation.py +++ b/python_modules/jupedsim/jupedsim/simulation.py @@ -19,6 +19,10 @@ CollisionFreeSpeedModelV2, CollisionFreeSpeedModelV2AgentParameters, ) +from jupedsim.models.collision_free_speed_v3 import ( + CollisionFreeSpeedModelV3, + CollisionFreeSpeedModelV3AgentParameters, +) from jupedsim.models.generalized_centrifugal_force import ( GeneralizedCentrifugalForceModel, GeneralizedCentrifugalForceModelAgentParameters, @@ -53,6 +57,7 @@ def __init__( CollisionFreeSpeedModel | GeneralizedCentrifugalForceModel | CollisionFreeSpeedModelV2 + | CollisionFreeSpeedModelV3 | SocialForceModel ), geometry: ( @@ -110,6 +115,9 @@ def __init__( elif isinstance(model, CollisionFreeSpeedModelV2): model_builder = py_jps.CollisionFreeSpeedModelV2Builder() py_jps_model = model_builder.build() + elif isinstance(model, CollisionFreeSpeedModelV3): + model_builder = py_jps.CollisionFreeSpeedModelV3Builder() + py_jps_model = model_builder.build() elif isinstance(model, GeneralizedCentrifugalForceModel): model_builder = py_jps.GeneralizedCentrifugalForceModelBuilder( strength_neighbor_repulsion=model.strength_neighbor_repulsion, @@ -248,6 +256,7 @@ def add_agent( GeneralizedCentrifugalForceModelAgentParameters | CollisionFreeSpeedModelAgentParameters | CollisionFreeSpeedModelV2AgentParameters + | CollisionFreeSpeedModelV3AgentParameters | SocialForceModelAgentParameters ), ) -> int: diff --git a/systemtest/test_model_properties.py b/systemtest/test_model_properties.py index afdd75b2d..5da3dd9b1 100644 --- a/systemtest/test_model_properties.py +++ b/systemtest/test_model_properties.py @@ -83,6 +83,50 @@ def test_set_model_parameters_collision_free_speed_model_v2( assert sim.agent(agent_id).model.range_geometry_repulsion == 8.0 +@pytest.fixture +def simulation_with_collision_free_speed_model_v3(): + return jps.Simulation( + model=jps.CollisionFreeSpeedModelV3(), + geometry=[(0, 0), (10, 0), (10, 10), (0, 10)], + ) + + +def test_set_model_parameters_collision_free_speed_model_v3( + simulation_with_collision_free_speed_model_v3, +): + sim = simulation_with_collision_free_speed_model_v3 + wp = sim.add_waypoint_stage((10, 1), 0.5) + journey_id = sim.add_journey(jps.JourneyDescription([wp])) + + agent = jps.CollisionFreeSpeedModelV3AgentParameters( + journey_id=journey_id, + stage_id=wp, + position=(1, 1), + ) + agent_id = sim.add_agent(agent) + + sim.agent(agent_id).model.v0 = 2.0 + assert sim.agent(agent_id).model.v0 == 2.0 + + sim.agent(agent_id).model.time_gap = 3.0 + assert sim.agent(agent_id).model.time_gap == 3.0 + + sim.agent(agent_id).model.radius = 4.0 + assert sim.agent(agent_id).model.radius == 4.0 + + sim.agent(agent_id).model.strength_neighbor_repulsion = 5.0 + assert sim.agent(agent_id).model.strength_neighbor_repulsion == 5.0 + + sim.agent(agent_id).model.range_neighbor_repulsion = 6.0 + assert sim.agent(agent_id).model.range_neighbor_repulsion == 6.0 + + sim.agent(agent_id).model.range_geometry_repulsion = 7.0 + assert sim.agent(agent_id).model.range_geometry_repulsion == 7.0 + + sim.agent(agent_id).model.range_geometry_repulsion = 8.0 + assert sim.agent(agent_id).model.range_geometry_repulsion == 8.0 + + @pytest.fixture def simulation_with_collision_free_speed_model(): return jps.Simulation( From 778523f38c624757fdfbad017750c20df1b9c235 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Wed, 1 Jan 2025 09:03:57 +0100 Subject: [PATCH 03/52] Running CollisionFreeSpeedModelV3. --- examples/example7_cfsm_v3.py | 11 ++++++----- libjupedsim/CMakeLists.txt | 1 + libjupedsim/src/agent.cpp | 21 +++++++++++++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/examples/example7_cfsm_v3.py b/examples/example7_cfsm_v3.py index f3e9eb923..18c11e961 100644 --- a/examples/example7_cfsm_v3.py +++ b/examples/example7_cfsm_v3.py @@ -14,9 +14,9 @@ def main(): geometry = shapely.GeometryCollection(shapely.box(0, -2.5, 50, 2.5)) exit_polygon = shapely.box(48, -2.5, 50, 2.5) - trajectory_file = "example_6.sqlite" + trajectory_file = "example_7.sqlite" simulation = jps.Simulation( - model=jps.CollisionFreeSpeedModelV2(), + model=jps.CollisionFreeSpeedModelV3(), geometry=geometry, trajectory_writer=jps.SqliteTrajectoryWriter( output_file=pathlib.Path(trajectory_file) @@ -36,7 +36,7 @@ def main(): for position in motivated_start_positions: simulation.add_agent( - jps.CollisionFreeSpeedModelV2AgentParameters( + jps.CollisionFreeSpeedModelV3AgentParameters( journey_id=journey_id, stage_id=exit_id, position=position, @@ -57,7 +57,7 @@ def main(): for position in slow_start_positions: simulation.add_agent( - jps.CollisionFreeSpeedModelV2AgentParameters( + jps.CollisionFreeSpeedModelV3AgentParameters( journey_id=journey_id, stage_id=exit_id, position=position, @@ -77,8 +77,9 @@ def main(): print("CTRL-C Recieved! Shuting down") sys.exit(1) print( - f"Simulation completed after {simulation.iteration_count()} iterations" + f"Simulation completed after {simulation.iteration_count()} iterations ({simulation.elapsed_time()} s)" ) + print(f"{trajectory_file = }") if __name__ == "__main__": diff --git a/libjupedsim/CMakeLists.txt b/libjupedsim/CMakeLists.txt index 6c4223036..8af2cf3fe 100644 --- a/libjupedsim/CMakeLists.txt +++ b/libjupedsim/CMakeLists.txt @@ -113,6 +113,7 @@ install( ${header_dest}/build_info.h ${header_dest}/collision_free_speed_model.h ${header_dest}/collision_free_speed_model_v2.h + ${header_dest}/collision_free_speed_model_v3.h ${header_dest}/error.h ${header_dest}/export.h ${header_dest}/generalized_centrifugal_force_model.h diff --git a/libjupedsim/src/agent.cpp b/libjupedsim/src/agent.cpp index fc56ab3a4..1af3755b4 100644 --- a/libjupedsim/src/agent.cpp +++ b/libjupedsim/src/agent.cpp @@ -161,6 +161,27 @@ JPS_Agent_GetCollisionFreeSpeedModelV2State(JPS_Agent handle, JPS_ErrorMessage* return nullptr; } +JPS_CollisionFreeSpeedModelV3State +JPS_Agent_GetCollisionFreeSpeedModelV3State(JPS_Agent handle, JPS_ErrorMessage* errorMessage) +{ + assert(handle); + const auto agent = reinterpret_cast(handle); + try { + auto& model = std::get(agent->model); + return reinterpret_cast(&model); + } catch(const std::exception& ex) { + if(errorMessage) { + *errorMessage = reinterpret_cast(new JPS_ErrorMessage_t{ex.what()}); + } + } catch(...) { + if(errorMessage) { + *errorMessage = reinterpret_cast( + new JPS_ErrorMessage_t{"Unknown internal error."}); + } + } + return nullptr; +} + JPS_SocialForceModelState JPS_Agent_GetSocialForceModelState(JPS_Agent handle, JPS_ErrorMessage* errorMessage) { From 6e65c65ed5bb9d9728bbef79ded78a6ccef89296 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Wed, 1 Jan 2025 10:23:12 +0100 Subject: [PATCH 04/52] update example --- examples/example7_cfsm_v3.py | 69 +++++++++++++++++------------------- 1 file changed, 32 insertions(+), 37 deletions(-) diff --git a/examples/example7_cfsm_v3.py b/examples/example7_cfsm_v3.py index 18c11e961..0d9f012b6 100644 --- a/examples/example7_cfsm_v3.py +++ b/examples/example7_cfsm_v3.py @@ -8,12 +8,28 @@ import jupedsim as jps import shapely +from shapely import Polygon def main(): - geometry = shapely.GeometryCollection(shapely.box(0, -2.5, 50, 2.5)) - exit_polygon = shapely.box(48, -2.5, 50, 2.5) - + room1 = Polygon([(0, 0), (10, 0), (10, 10), (0, 10)]) # Room 1 (10m x 10m) + room2 = Polygon( + [(15, 0), (25, 0), (25, 10), (15, 10)] + ) # Room 2 (10m x 10m) + width = 0.8 + num_agents = 10 + corridor = Polygon( + [ + (10, 5 - width / 2), + (15, 5 - width / 2), + (15, 5 + width / 2), + (10, 5 + width / 2), + ] + ) + geometry = room1.union(room2).union(corridor) + # geometry = shapely.GeometryCollection(shapely.box(0, -2.5, 50, 2.5)) + # exit_polygon = shapely.box(48, -2.5, 50, 2.5) # + exit_polygon = Polygon([(24, 4.5), (25, 4.5), (25, 5.5), (24, 5.5)]) trajectory_file = "example_7.sqlite" simulation = jps.Simulation( model=jps.CollisionFreeSpeedModelV3(), @@ -27,54 +43,33 @@ def main(): journey = jps.JourneyDescription([exit_id]) journey_id = simulation.add_journey(journey) - motivated_start_positions = jps.distribute_by_number( - polygon=shapely.box(0, -2.5, 5, 2.5), - number_of_agents=30, - distance_to_agents=0.3, - distance_to_polygon=0.2, - ) - - for position in motivated_start_positions: - simulation.add_agent( - jps.CollisionFreeSpeedModelV3AgentParameters( - journey_id=journey_id, - stage_id=exit_id, - position=position, - radius=0.12, - strength_neighbor_repulsion=8, - range_neighbor_repulsion=0.1, - strength_geometry_repulsion=5, - range_geometry_repulsion=0.1, - ) - ) - - slow_start_positions = jps.distribute_by_number( - polygon=shapely.box(15, -2.5, 20, 2.5), - number_of_agents=30, - distance_to_agents=0.3, + start_positions = jps.distribute_by_number( + polygon=Polygon([(0, 0), (5, 0), (5, 10), (0, 10)]), + # shapely.box(0, -2.5, 5, 2.5), + number_of_agents=num_agents, + distance_to_agents=0.5, distance_to_polygon=0.2, ) - for position in slow_start_positions: + for position in start_positions: simulation.add_agent( jps.CollisionFreeSpeedModelV3AgentParameters( journey_id=journey_id, stage_id=exit_id, position=position, - radius=0.12, - strength_neighbor_repulsion=30, - range_neighbor_repulsion=0.1, - strength_geometry_repulsion=15, - range_geometry_repulsion=0.1, - v0=0.3, + radius=0.2, + # strength_neighbor_repulsion=8, + # range_neighbor_repulsion=0.1, + # strength_geometry_repulsion=5, + # range_geometry_repulsion=0.1, ) ) - while simulation.agent_count() > 0: + while simulation.agent_count() > 0 and simulation.iteration_count() < 2000: try: simulation.iterate() except KeyboardInterrupt: - print("CTRL-C Recieved! Shuting down") + print("CTRL-C Received! Shutting down") sys.exit(1) print( f"Simulation completed after {simulation.iteration_count()} iterations ({simulation.elapsed_time()} s)" From 0e1838ebd19b3a5303ce54e49ec046be9b648554 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Fri, 3 Jan 2025 13:13:25 +0100 Subject: [PATCH 05/52] Rename model CollisionFreeSpeedModelV3 to AVM --- .../{example7_cfsm_v3.py => example7_avm.py} | 6 +- libjupedsim/CMakeLists.txt | 4 +- libjupedsim/include/jupedsim/agent.h | 10 +- ...del_v3.h => anticipation_velocity_model.h} | 90 +++++----- libjupedsim/include/jupedsim/jupedsim.h | 2 +- libjupedsim/include/jupedsim/simulation.h | 6 +- libjupedsim/include/jupedsim/types.h | 2 +- libjupedsim/src/agent.cpp | 10 +- .../src/anticipation_velocity_model.cpp | 169 ++++++++++++++++++ .../src/collision_free_speed_model_v3.cpp | 169 ------------------ libjupedsim/src/simulation.cpp | 14 +- libsimulator/CMakeLists.txt | 12 +- ...elV3.cpp => AnticipationVelocityModel.cpp} | 61 +++---- ...elV3.hpp => AnticipationVelocityModel.hpp} | 8 +- .../src/AnticipationVelocityModelBuilder.cpp | 12 ++ .../src/AnticipationVelocityModelBuilder.hpp | 11 ++ ....hpp => AnticipationVelocityModelData.hpp} | 8 +- ...pp => AnticipationVelocityModelUpdate.hpp} | 2 +- .../src/CollisionFreeSpeedModelV3Builder.cpp | 12 -- .../src/CollisionFreeSpeedModelV3Builder.hpp | 11 -- libsimulator/src/GenericAgent.hpp | 4 +- libsimulator/src/OperationalModelType.hpp | 2 +- libsimulator/src/OperationalModelUpdate.hpp | 4 +- python_bindings_jupedsim/CMakeLists.txt | 2 +- python_bindings_jupedsim/agent.cpp | 8 +- ...v3.cpp => anticipation_velocity_model.cpp} | 80 ++++----- .../bindings_jupedsim.cpp | 4 +- python_bindings_jupedsim/simulation.cpp | 4 +- python_bindings_jupedsim/wrapper.hpp | 5 +- python_modules/jupedsim/jupedsim/__init__.py | 14 +- python_modules/jupedsim/jupedsim/agent.py | 9 +- ...d_v3.py => anticipation_velocity_model.py} | 39 ++-- .../jupedsim/jupedsim/simulation.py | 14 +- systemtest/test_model_properties.py | 12 +- 34 files changed, 415 insertions(+), 405 deletions(-) rename examples/{example7_cfsm_v3.py => example7_avm.py} (95%) rename libjupedsim/include/jupedsim/{collision_free_speed_model_v3.h => anticipation_velocity_model.h} (60%) create mode 100644 libjupedsim/src/anticipation_velocity_model.cpp delete mode 100644 libjupedsim/src/collision_free_speed_model_v3.cpp rename libsimulator/src/{CollisionFreeSpeedModelV3.cpp => AnticipationVelocityModel.cpp} (78%) rename libsimulator/src/{CollisionFreeSpeedModelV3.hpp => AnticipationVelocityModel.hpp} (85%) create mode 100644 libsimulator/src/AnticipationVelocityModelBuilder.cpp create mode 100644 libsimulator/src/AnticipationVelocityModelBuilder.hpp rename libsimulator/src/{CollisionFreeSpeedModelV3Data.hpp => AnticipationVelocityModelData.hpp} (81%) rename libsimulator/src/{CollisionFreeSpeedModelV3Update.hpp => AnticipationVelocityModelUpdate.hpp} (82%) delete mode 100644 libsimulator/src/CollisionFreeSpeedModelV3Builder.cpp delete mode 100644 libsimulator/src/CollisionFreeSpeedModelV3Builder.hpp rename python_bindings_jupedsim/{collision_free_speed_model_v3.cpp => anticipation_velocity_model.cpp} (60%) rename python_modules/jupedsim/jupedsim/models/{collision_free_speed_v3.py => anticipation_velocity_model.py} (76%) diff --git a/examples/example7_cfsm_v3.py b/examples/example7_avm.py similarity index 95% rename from examples/example7_cfsm_v3.py rename to examples/example7_avm.py index 0d9f012b6..06a46fa1d 100644 --- a/examples/example7_cfsm_v3.py +++ b/examples/example7_avm.py @@ -32,7 +32,7 @@ def main(): exit_polygon = Polygon([(24, 4.5), (25, 4.5), (25, 5.5), (24, 5.5)]) trajectory_file = "example_7.sqlite" simulation = jps.Simulation( - model=jps.CollisionFreeSpeedModelV3(), + model=jps.AnticipationVelocityModel(), geometry=geometry, trajectory_writer=jps.SqliteTrajectoryWriter( output_file=pathlib.Path(trajectory_file) @@ -53,7 +53,7 @@ def main(): for position in start_positions: simulation.add_agent( - jps.CollisionFreeSpeedModelV3AgentParameters( + jps.AnticipationVelocityModelAgentParameters( journey_id=journey_id, stage_id=exit_id, position=position, @@ -65,7 +65,7 @@ def main(): ) ) - while simulation.agent_count() > 0 and simulation.iteration_count() < 2000: + while simulation.agent_count() > 0 and simulation.iteration_count() < 3000: try: simulation.iterate() except KeyboardInterrupt: diff --git a/libjupedsim/CMakeLists.txt b/libjupedsim/CMakeLists.txt index 8af2cf3fe..541100dbf 100644 --- a/libjupedsim/CMakeLists.txt +++ b/libjupedsim/CMakeLists.txt @@ -11,7 +11,7 @@ add_library(jupedsim_obj OBJECT src/build_info.cpp src/collision_free_speed_model.cpp src/collision_free_speed_model_v2.cpp - src/collision_free_speed_model_v3.cpp + src/anticipation_velocity_model.cpp src/error.cpp src/generalized_centrifugal_force_model.cpp src/geometry.cpp @@ -113,7 +113,7 @@ install( ${header_dest}/build_info.h ${header_dest}/collision_free_speed_model.h ${header_dest}/collision_free_speed_model_v2.h - ${header_dest}/collision_free_speed_model_v3.h + ${header_dest}/anticipation_velocity_model.h ${header_dest}/error.h ${header_dest}/export.h ${header_dest}/generalized_centrifugal_force_model.h diff --git a/libjupedsim/include/jupedsim/agent.h b/libjupedsim/include/jupedsim/agent.h index 41107c391..ff1e683d7 100644 --- a/libjupedsim/include/jupedsim/agent.h +++ b/libjupedsim/include/jupedsim/agent.h @@ -4,7 +4,7 @@ #include "collision_free_speed_model.h" #include "collision_free_speed_model_v2.h" -#include "collision_free_speed_model_v3.h" +#include "anticipation_velocity_model.h" #include "error.h" #include "export.h" #include "generalized_centrifugal_force_model.h" @@ -118,14 +118,14 @@ JUPEDSIM_API JPS_CollisionFreeSpeedModelV2State JPS_Agent_GetCollisionFreeSpeedModelV2State(JPS_Agent handle, JPS_ErrorMessage* errorMessage); /** - * Access Collision Free Speed model V3 state. - * Precondition: Agent needs to use Collision Free Speed model V3 + * Access Anticipation Velocity Model state. + * Precondition: Agent needs to use Anticipation Velocity Model * @param handle of the agent to access. * @param[out] errorMessage if not NULL: will be set to a JPS_ErrorMessage in case of an error. * @return state or NULL on error */ -JUPEDSIM_API JPS_CollisionFreeSpeedModelV3State -JPS_Agent_GetCollisionFreeSpeedModelV3State(JPS_Agent handle, JPS_ErrorMessage* errorMessage); +JUPEDSIM_API JPS_AnticipationVelocityModelState +JPS_Agent_GetAnticipationVelocityModelState(JPS_Agent handle, JPS_ErrorMessage* errorMessage); /** diff --git a/libjupedsim/include/jupedsim/collision_free_speed_model_v3.h b/libjupedsim/include/jupedsim/anticipation_velocity_model.h similarity index 60% rename from libjupedsim/include/jupedsim/collision_free_speed_model_v3.h rename to libjupedsim/include/jupedsim/anticipation_velocity_model.h index bbc4a9f0a..9da4714cc 100644 --- a/libjupedsim/include/jupedsim/collision_free_speed_model_v3.h +++ b/libjupedsim/include/jupedsim/anticipation_velocity_model.h @@ -12,54 +12,54 @@ extern "C" { #endif /** - * Opaque type for a Collision Free Speed Model V3 Builder + * Opaque type for a Anticipation Velocity Model Builder */ -typedef struct JPS_CollisionFreeSpeedModelV3Builder_t* JPS_CollisionFreeSpeedModelV3Builder; +typedef struct JPS_AnticipationVelocityModelBuilder_t* JPS_AnticipationVelocityModelBuilder; /** - * Creates a Collision Free Speed Model V3 builder. + * Creates a Anticipation Velocity Model builder. * @return the builder */ -JUPEDSIM_API JPS_CollisionFreeSpeedModelV3Builder JPS_CollisionFreeSpeedModelV3Builder_Create(); +JUPEDSIM_API JPS_AnticipationVelocityModelBuilder JPS_AnticipationVelocityModelBuilder_Create(); /** - * Creates a JPS_OperationalModel of type Collision Free Speed Model V3 from the - * JPS_CollisionFreeSpeedModelV3Builder. + * Creates a JPS_OperationalModel of type Anticipation Velocity Model from the + * JPS_AnticipationVelocityModelBuilder. * @param handle the builder to operate on * @param[out] errorMessage if not NULL: will be set to a JPS_ErrorMessage in case of an error - * @return a JPS_CollisionFreeSpeedModelV3 or NULL if an error occured. + * @return a JPS_AnticipationVelocityModel or NULL if an error occured. */ -JUPEDSIM_API JPS_OperationalModel JPS_CollisionFreeSpeedModelV3Builder_Build( - JPS_CollisionFreeSpeedModelV3Builder handle, +JUPEDSIM_API JPS_OperationalModel JPS_AnticipationVelocityModelBuilder_Build( + JPS_AnticipationVelocityModelBuilder handle, JPS_ErrorMessage* errorMessage); /** - * Frees a JPS_CollisionFreeSpeedModelV3Builder - * @param handle to the JPS_CollisionFreeSpeedModelV3Builder to free. + * Frees a JPS_AnticipationVelocityModelBuilder + * @param handle to the JPS_AnticipationVelocityModelBuilder to free. */ JUPEDSIM_API void -JPS_CollisionFreeSpeedModelV3Builder_Free(JPS_CollisionFreeSpeedModelV3Builder handle); +JPS_AnticipationVelocityModelBuilder_Free(JPS_AnticipationVelocityModelBuilder handle); /** - * Opaque type of Collision Free Speed V3 model state + * Opaque type of Anticipation Velocity Model state */ -typedef struct JPS_CollisionFreeSpeedModelV3State_t* JPS_CollisionFreeSpeedModelV3State; +typedef struct JPS_AnticipationVelocityModelState_t* JPS_AnticipationVelocityModelState; /** * Read strength neighbor repulsion of this agent. * @param handle of the Agent to access. * @return strength neighbor repulsion of this agent */ -JUPEDSIM_API double JPS_CollisionFreeSpeedModelV3State_GetStrengthNeighborRepulsion( - JPS_CollisionFreeSpeedModelV3State handle); +JUPEDSIM_API double JPS_AnticipationVelocityModelState_GetStrengthNeighborRepulsion( + JPS_AnticipationVelocityModelState handle); /** * Write strength neighbor repulsion of this agent. * @param handle of the Agent to access. * @param strengthNeighborRepulsion of this agent. */ -JUPEDSIM_API void JPS_CollisionFreeSpeedModelV3State_SetStrengthNeighborRepulsion( - JPS_CollisionFreeSpeedModelV3State handle, +JUPEDSIM_API void JPS_AnticipationVelocityModelState_SetStrengthNeighborRepulsion( + JPS_AnticipationVelocityModelState handle, double strengthNeighborRepulsion); /** @@ -67,16 +67,16 @@ JUPEDSIM_API void JPS_CollisionFreeSpeedModelV3State_SetStrengthNeighborRepulsio * @param handle of the Agent to access. * @return range neighbor repulsion of this agent */ -JUPEDSIM_API double JPS_CollisionFreeSpeedModelV3State_GetRangeNeighborRepulsion( - JPS_CollisionFreeSpeedModelV3State handle); +JUPEDSIM_API double JPS_AnticipationVelocityModelState_GetRangeNeighborRepulsion( + JPS_AnticipationVelocityModelState handle); /** * Write range neighbor repulsion of this agent. * @param handle of the Agent to access. * @param rangeNeighborRepulsion of this agent. */ -JUPEDSIM_API void JPS_CollisionFreeSpeedModelV3State_SetRangeNeighborRepulsion( - JPS_CollisionFreeSpeedModelV3State handle, +JUPEDSIM_API void JPS_AnticipationVelocityModelState_SetRangeNeighborRepulsion( + JPS_AnticipationVelocityModelState handle, double rangeNeighborRepulsion); /** @@ -84,16 +84,16 @@ JUPEDSIM_API void JPS_CollisionFreeSpeedModelV3State_SetRangeNeighborRepulsion( * @param handle of the Agent to access. * @return strength geometry repulsion of this agent */ -JUPEDSIM_API double JPS_CollisionFreeSpeedModelV3State_GetStrengthGeometryRepulsion( - JPS_CollisionFreeSpeedModelV3State handle); +JUPEDSIM_API double JPS_AnticipationVelocityModelState_GetStrengthGeometryRepulsion( + JPS_AnticipationVelocityModelState handle); /** * Write strength geometry repulsion of this agent. * @param handle of the Agent to access. * @param strengthGeometryRepulsion of this agent. */ -JUPEDSIM_API void JPS_CollisionFreeSpeedModelV3State_SetStrengthGeometryRepulsion( - JPS_CollisionFreeSpeedModelV3State handle, +JUPEDSIM_API void JPS_AnticipationVelocityModelState_SetStrengthGeometryRepulsion( + JPS_AnticipationVelocityModelState handle, double strengthGeometryRepulsion); /** @@ -101,16 +101,16 @@ JUPEDSIM_API void JPS_CollisionFreeSpeedModelV3State_SetStrengthGeometryRepulsio * @param handle of the Agent to access. * @return range geometry repulsion of this agent */ -JUPEDSIM_API double JPS_CollisionFreeSpeedModelV3State_GetRangeGeometryRepulsion( - JPS_CollisionFreeSpeedModelV3State handle); +JUPEDSIM_API double JPS_AnticipationVelocityModelState_GetRangeGeometryRepulsion( + JPS_AnticipationVelocityModelState handle); /** * Write strength neighbor repulsion of this agent. * @param handle of the Agent to access. * @param rangeGeometryRepulsion of this agent. */ -JUPEDSIM_API void JPS_CollisionFreeSpeedModelV3State_SetRangeGeometryRepulsion( - JPS_CollisionFreeSpeedModelV3State handle, +JUPEDSIM_API void JPS_AnticipationVelocityModelState_SetRangeGeometryRepulsion( + JPS_AnticipationVelocityModelState handle, double rangeGeometryRepulsion); /** @@ -119,7 +119,7 @@ JUPEDSIM_API void JPS_CollisionFreeSpeedModelV3State_SetRangeGeometryRepulsion( * @return e0 of this agent */ JUPEDSIM_API JPS_Point -JPS_CollisionFreeSpeedModelV3State_GetE0(JPS_CollisionFreeSpeedModelV3State handle); +JPS_AnticipationVelocityModelState_GetE0(JPS_AnticipationVelocityModelState handle); /** * Write e0 of this agent. @@ -127,7 +127,7 @@ JPS_CollisionFreeSpeedModelV3State_GetE0(JPS_CollisionFreeSpeedModelV3State hand * @param e0 of this agent. */ JUPEDSIM_API void -JPS_CollisionFreeSpeedModelV3State_SetE0(JPS_CollisionFreeSpeedModelV3State handle, JPS_Point e0); +JPS_AnticipationVelocityModelState_SetE0(JPS_AnticipationVelocityModelState handle, JPS_Point e0); /** * Read time gap of this agent. @@ -135,15 +135,15 @@ JPS_CollisionFreeSpeedModelV3State_SetE0(JPS_CollisionFreeSpeedModelV3State hand * @return time gap of this agent */ JUPEDSIM_API double -JPS_CollisionFreeSpeedModelV3State_GetTimeGap(JPS_CollisionFreeSpeedModelV3State handle); +JPS_AnticipationVelocityModelState_GetTimeGap(JPS_AnticipationVelocityModelState handle); /** * Write time gap of this agent. * @param handle of the Agent to access. * @param time_gap of this agent. */ -JUPEDSIM_API void JPS_CollisionFreeSpeedModelV3State_SetTimeGap( - JPS_CollisionFreeSpeedModelV3State handle, +JUPEDSIM_API void JPS_AnticipationVelocityModelState_SetTimeGap( + JPS_AnticipationVelocityModelState handle, double time_gap); /** @@ -152,7 +152,7 @@ JUPEDSIM_API void JPS_CollisionFreeSpeedModelV3State_SetTimeGap( * @return tau of this agent */ JUPEDSIM_API double -JPS_CollisionFreeSpeedModelV3State_GetTau(JPS_CollisionFreeSpeedModelV3State handle); +JPS_AnticipationVelocityModelState_GetTau(JPS_AnticipationVelocityModelState handle); /** * Write tau of this agent. @@ -160,7 +160,7 @@ JPS_CollisionFreeSpeedModelV3State_GetTau(JPS_CollisionFreeSpeedModelV3State han * @param tau of this agent. */ JUPEDSIM_API void -JPS_CollisionFreeSpeedModelV3State_SetTau(JPS_CollisionFreeSpeedModelV3State handle, double tau); +JPS_AnticipationVelocityModelState_SetTau(JPS_AnticipationVelocityModelState handle, double tau); /** * Read v0 of this agent. @@ -168,7 +168,7 @@ JPS_CollisionFreeSpeedModelV3State_SetTau(JPS_CollisionFreeSpeedModelV3State han * @return v0 of this agent */ JUPEDSIM_API double -JPS_CollisionFreeSpeedModelV3State_GetV0(JPS_CollisionFreeSpeedModelV3State handle); +JPS_AnticipationVelocityModelState_GetV0(JPS_AnticipationVelocityModelState handle); /** * Write v0 of this agent. @@ -176,7 +176,7 @@ JPS_CollisionFreeSpeedModelV3State_GetV0(JPS_CollisionFreeSpeedModelV3State hand * @param v0 of this agent. */ JUPEDSIM_API void -JPS_CollisionFreeSpeedModelV3State_SetV0(JPS_CollisionFreeSpeedModelV3State handle, double v0); +JPS_AnticipationVelocityModelState_SetV0(JPS_AnticipationVelocityModelState handle, double v0); /** * Read radius of this agent. @@ -184,21 +184,21 @@ JPS_CollisionFreeSpeedModelV3State_SetV0(JPS_CollisionFreeSpeedModelV3State hand * @return radius of this agent */ JUPEDSIM_API double -JPS_CollisionFreeSpeedModelV3State_GetRadius(JPS_CollisionFreeSpeedModelV3State handle); +JPS_AnticipationVelocityModelState_GetRadius(JPS_AnticipationVelocityModelState handle); /** * Write radius of this agent in meters. * @param handle of the Agent to access. * @param radius (m) of this agent. */ -JUPEDSIM_API void JPS_CollisionFreeSpeedModelV3State_SetRadius( - JPS_CollisionFreeSpeedModelV3State handle, +JUPEDSIM_API void JPS_AnticipationVelocityModelState_SetRadius( + JPS_AnticipationVelocityModelState handle, double radius); /** - * Describes parameters of an Agent in Collision Free Speed Model V3 + * Describes parameters of an Agent in Anticipation Velocity Model */ -typedef struct JPS_CollisionFreeSpeedModelV3AgentParameters { +typedef struct JPS_AnticipationVelocityModelAgentParameters { /** * Position of the agent. * The position needs to inside the accessible area. @@ -246,7 +246,7 @@ typedef struct JPS_CollisionFreeSpeedModelV3AgentParameters { */ double rangeGeometryRepulsion{0.02}; -} JPS_CollisionFreeSpeedModelV3AgentParameters; +} JPS_AnticipationVelocityModelAgentParameters; #ifdef __cplusplus } diff --git a/libjupedsim/include/jupedsim/jupedsim.h b/libjupedsim/include/jupedsim/jupedsim.h index 1609ac3e2..18bf59787 100644 --- a/libjupedsim/include/jupedsim/jupedsim.h +++ b/libjupedsim/include/jupedsim/jupedsim.h @@ -6,7 +6,7 @@ #include "build_info.h" #include "collision_free_speed_model.h" #include "collision_free_speed_model_v2.h" -#include "collision_free_speed_model_v3.h" +#include "anticipation_velocity_model.h" #include "error.h" #include "export.h" #include "generalized_centrifugal_force_model.h" diff --git a/libjupedsim/include/jupedsim/simulation.h b/libjupedsim/include/jupedsim/simulation.h index 33b222fe9..8d412de6a 100644 --- a/libjupedsim/include/jupedsim/simulation.h +++ b/libjupedsim/include/jupedsim/simulation.h @@ -5,7 +5,7 @@ #include "agent.h" #include "collision_free_speed_model.h" #include "collision_free_speed_model_v2.h" -#include "collision_free_speed_model_v3.h" +#include "anticipation_velocity_model.h" #include "error.h" #include "export.h" #include "generalized_centrifugal_force_model.h" @@ -200,9 +200,9 @@ JUPEDSIM_API JPS_AgentId JPS_Simulation_AddCollisionFreeSpeedModelV2Agent( * error. * @return id of the new agent or 0 if the agent could not be added due to an error. */ -JUPEDSIM_API JPS_AgentId JPS_Simulation_AddCollisionFreeSpeedModelV3Agent( +JUPEDSIM_API JPS_AgentId JPS_Simulation_AddAnticipationVelocityModelAgent( JPS_Simulation handle, - JPS_CollisionFreeSpeedModelV3AgentParameters parameters, + JPS_AnticipationVelocityModelAgentParameters parameters, JPS_ErrorMessage* errorMessage); diff --git a/libjupedsim/include/jupedsim/types.h b/libjupedsim/include/jupedsim/types.h index 5614a5aa8..1520d7145 100644 --- a/libjupedsim/include/jupedsim/types.h +++ b/libjupedsim/include/jupedsim/types.h @@ -61,7 +61,7 @@ typedef enum JPS_ModelType { JPS_GeneralizedCentrifugalForceModel, JPS_CollisionFreeSpeedModel, JPS_CollisionFreeSpeedModelV2, - JPS_CollisionFreeSpeedModelV3, + JPS_AnticipationVelocityModel, JPS_SocialForceModel } JPS_ModelType; diff --git a/libjupedsim/src/agent.cpp b/libjupedsim/src/agent.cpp index 1af3755b4..7238d0606 100644 --- a/libjupedsim/src/agent.cpp +++ b/libjupedsim/src/agent.cpp @@ -91,7 +91,7 @@ JPS_ModelType JPS_Agent_GetModelType(JPS_Agent handle) case 2: return JPS_CollisionFreeSpeedModelV2; case 3: - return JPS_CollisionFreeSpeedModelV3; + return JPS_AnticipationVelocityModel; case 4: return JPS_SocialForceModel; } @@ -161,14 +161,14 @@ JPS_Agent_GetCollisionFreeSpeedModelV2State(JPS_Agent handle, JPS_ErrorMessage* return nullptr; } -JPS_CollisionFreeSpeedModelV3State -JPS_Agent_GetCollisionFreeSpeedModelV3State(JPS_Agent handle, JPS_ErrorMessage* errorMessage) +JPS_AnticipationVelocityModelState +JPS_Agent_GetAnticipationVelocityModelState(JPS_Agent handle, JPS_ErrorMessage* errorMessage) { assert(handle); const auto agent = reinterpret_cast(handle); try { - auto& model = std::get(agent->model); - return reinterpret_cast(&model); + auto& model = std::get(agent->model); + return reinterpret_cast(&model); } catch(const std::exception& ex) { if(errorMessage) { *errorMessage = reinterpret_cast(new JPS_ErrorMessage_t{ex.what()}); diff --git a/libjupedsim/src/anticipation_velocity_model.cpp b/libjupedsim/src/anticipation_velocity_model.cpp new file mode 100644 index 000000000..e4e99c417 --- /dev/null +++ b/libjupedsim/src/anticipation_velocity_model.cpp @@ -0,0 +1,169 @@ +// Copyright © 2012-2024 Forschungszentrum Jülich GmbH +// SPDX-License-Identifier: LGPL-3.0-or-later +#include "jupedsim/anticipation_velocity_model.h" +#include "jupedsim/error.h" + +#include "Conversion.hpp" +#include "ErrorMessage.hpp" + +#include +#include +#include + +using jupedsim::detail::intoJPS_Point; +using jupedsim::detail::intoPoint; +using jupedsim::detail::intoTuple; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// Anticipation Velocity Model Builder +//////////////////////////////////////////////////////////////////////////////////////////////////// +JUPEDSIM_API JPS_AnticipationVelocityModelBuilder JPS_AnticipationVelocityModelBuilder_Create() +{ + return reinterpret_cast( + new AnticipationVelocityModelBuilder()); +} + +JUPEDSIM_API JPS_OperationalModel JPS_AnticipationVelocityModelBuilder_Build( + JPS_AnticipationVelocityModelBuilder handle, + JPS_ErrorMessage* errorMessage) +{ + assert(handle != nullptr); + auto builder = reinterpret_cast(handle); + JPS_OperationalModel result{}; + try { + result = + reinterpret_cast(new AnticipationVelocityModel(builder->Build())); + } catch(const std::exception& ex) { + if(errorMessage) { + *errorMessage = reinterpret_cast(new JPS_ErrorMessage_t{ex.what()}); + } + } catch(...) { + if(errorMessage) { + *errorMessage = reinterpret_cast( + new JPS_ErrorMessage_t{"Unknown internal error."}); + } + } + return result; +} + +JUPEDSIM_API void +JPS_AnticipationVelocityModelBuilder_Free(JPS_AnticipationVelocityModelBuilder handle) +{ + delete reinterpret_cast(handle); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// AnticipationVelocityModelState +//////////////////////////////////////////////////////////////////////////////////////////////////// +double JPS_AnticipationVelocityModelState_GetStrengthNeighborRepulsion( + JPS_AnticipationVelocityModelState handle) +{ + assert(handle); + const auto state = reinterpret_cast(handle); + return state->strengthNeighborRepulsion; +} + +void JPS_AnticipationVelocityModelState_SetStrengthNeighborRepulsion( + JPS_AnticipationVelocityModelState handle, + double strengthNeighborRepulsion) +{ + assert(handle); + auto state = reinterpret_cast(handle); + state->strengthNeighborRepulsion = strengthNeighborRepulsion; +} + +double JPS_AnticipationVelocityModelState_GetRangeNeighborRepulsion( + JPS_AnticipationVelocityModelState handle) +{ + assert(handle); + const auto state = reinterpret_cast(handle); + return state->rangeNeighborRepulsion; +} + +void JPS_AnticipationVelocityModelState_SetRangeNeighborRepulsion( + JPS_AnticipationVelocityModelState handle, + double rangeNeighborRepulsion) +{ + assert(handle); + auto state = reinterpret_cast(handle); + state->rangeNeighborRepulsion = rangeNeighborRepulsion; +} + +double JPS_AnticipationVelocityModelState_GetStrengthGeometryRepulsion( + JPS_AnticipationVelocityModelState handle) +{ + assert(handle); + const auto state = reinterpret_cast(handle); + return state->strengthGeometryRepulsion; +} + +void JPS_AnticipationVelocityModelState_SetStrengthGeometryRepulsion( + JPS_AnticipationVelocityModelState handle, + double strengthGeometryRepulsion) +{ + assert(handle); + auto state = reinterpret_cast(handle); + state->strengthGeometryRepulsion = strengthGeometryRepulsion; +} + +double JPS_AnticipationVelocityModelState_GetRangeGeometryRepulsion( + JPS_AnticipationVelocityModelState handle) +{ + assert(handle); + const auto state = reinterpret_cast(handle); + return state->rangeNeighborRepulsion; +} + +void JPS_AnticipationVelocityModelState_SetRangeGeometryRepulsion( + JPS_AnticipationVelocityModelState handle, + double rangeNeighborRepulsion) +{ + assert(handle); + auto state = reinterpret_cast(handle); + state->rangeNeighborRepulsion = rangeNeighborRepulsion; +} + +double JPS_AnticipationVelocityModelState_GetTimeGap(JPS_AnticipationVelocityModelState handle) +{ + assert(handle); + const auto state = reinterpret_cast(handle); + return state->timeGap; +} + +void JPS_AnticipationVelocityModelState_SetTimeGap( + JPS_AnticipationVelocityModelState handle, + double time_gap) +{ + assert(handle); + auto state = reinterpret_cast(handle); + state->timeGap = time_gap; +} + +double JPS_AnticipationVelocityModelState_GetV0(JPS_AnticipationVelocityModelState handle) +{ + assert(handle); + const auto state = reinterpret_cast(handle); + return state->v0; +} + +void JPS_AnticipationVelocityModelState_SetV0(JPS_AnticipationVelocityModelState handle, double v0) +{ + assert(handle); + auto state = reinterpret_cast(handle); + state->v0 = v0; +} +double JPS_AnticipationVelocityModelState_GetRadius(JPS_AnticipationVelocityModelState handle) +{ + assert(handle); + const auto state = reinterpret_cast(handle); + return state->radius; +} + +void JPS_AnticipationVelocityModelState_SetRadius( + JPS_AnticipationVelocityModelState handle, + double radius) +{ + assert(handle); + auto state = reinterpret_cast(handle); + state->radius = radius; +} diff --git a/libjupedsim/src/collision_free_speed_model_v3.cpp b/libjupedsim/src/collision_free_speed_model_v3.cpp deleted file mode 100644 index 607a4ff5b..000000000 --- a/libjupedsim/src/collision_free_speed_model_v3.cpp +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright © 2012-2024 Forschungszentrum Jülich GmbH -// SPDX-License-Identifier: LGPL-3.0-or-later -#include "jupedsim/collision_free_speed_model.h" -#include "jupedsim/error.h" - -#include "Conversion.hpp" -#include "ErrorMessage.hpp" - -#include -#include -#include - -using jupedsim::detail::intoJPS_Point; -using jupedsim::detail::intoPoint; -using jupedsim::detail::intoTuple; - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// Collision Free Speed Model V3 Builder -//////////////////////////////////////////////////////////////////////////////////////////////////// -JUPEDSIM_API JPS_CollisionFreeSpeedModelV3Builder JPS_CollisionFreeSpeedModelV3Builder_Create() -{ - return reinterpret_cast( - new CollisionFreeSpeedModelV3Builder()); -} - -JUPEDSIM_API JPS_OperationalModel JPS_CollisionFreeSpeedModelV3Builder_Build( - JPS_CollisionFreeSpeedModelV3Builder handle, - JPS_ErrorMessage* errorMessage) -{ - assert(handle != nullptr); - auto builder = reinterpret_cast(handle); - JPS_OperationalModel result{}; - try { - result = - reinterpret_cast(new CollisionFreeSpeedModelV3(builder->Build())); - } catch(const std::exception& ex) { - if(errorMessage) { - *errorMessage = reinterpret_cast(new JPS_ErrorMessage_t{ex.what()}); - } - } catch(...) { - if(errorMessage) { - *errorMessage = reinterpret_cast( - new JPS_ErrorMessage_t{"Unknown internal error."}); - } - } - return result; -} - -JUPEDSIM_API void -JPS_CollisionFreeSpeedModelV3Builder_Free(JPS_CollisionFreeSpeedModelV3Builder handle) -{ - delete reinterpret_cast(handle); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// CollisionFreeSpeedModelV3State -//////////////////////////////////////////////////////////////////////////////////////////////////// -double JPS_CollisionFreeSpeedModelV3State_GetStrengthNeighborRepulsion( - JPS_CollisionFreeSpeedModelV3State handle) -{ - assert(handle); - const auto state = reinterpret_cast(handle); - return state->strengthNeighborRepulsion; -} - -void JPS_CollisionFreeSpeedModelV3State_SetStrengthNeighborRepulsion( - JPS_CollisionFreeSpeedModelV3State handle, - double strengthNeighborRepulsion) -{ - assert(handle); - auto state = reinterpret_cast(handle); - state->strengthNeighborRepulsion = strengthNeighborRepulsion; -} - -double JPS_CollisionFreeSpeedModelV3State_GetRangeNeighborRepulsion( - JPS_CollisionFreeSpeedModelV3State handle) -{ - assert(handle); - const auto state = reinterpret_cast(handle); - return state->rangeNeighborRepulsion; -} - -void JPS_CollisionFreeSpeedModelV3State_SetRangeNeighborRepulsion( - JPS_CollisionFreeSpeedModelV3State handle, - double rangeNeighborRepulsion) -{ - assert(handle); - auto state = reinterpret_cast(handle); - state->rangeNeighborRepulsion = rangeNeighborRepulsion; -} - -double JPS_CollisionFreeSpeedModelV3State_GetStrengthGeometryRepulsion( - JPS_CollisionFreeSpeedModelV3State handle) -{ - assert(handle); - const auto state = reinterpret_cast(handle); - return state->strengthGeometryRepulsion; -} - -void JPS_CollisionFreeSpeedModelV3State_SetStrengthGeometryRepulsion( - JPS_CollisionFreeSpeedModelV3State handle, - double strengthGeometryRepulsion) -{ - assert(handle); - auto state = reinterpret_cast(handle); - state->strengthGeometryRepulsion = strengthGeometryRepulsion; -} - -double JPS_CollisionFreeSpeedModelV3State_GetRangeGeometryRepulsion( - JPS_CollisionFreeSpeedModelV3State handle) -{ - assert(handle); - const auto state = reinterpret_cast(handle); - return state->rangeNeighborRepulsion; -} - -void JPS_CollisionFreeSpeedModelV3State_SetRangeGeometryRepulsion( - JPS_CollisionFreeSpeedModelV3State handle, - double rangeNeighborRepulsion) -{ - assert(handle); - auto state = reinterpret_cast(handle); - state->rangeNeighborRepulsion = rangeNeighborRepulsion; -} - -double JPS_CollisionFreeSpeedModelV3State_GetTimeGap(JPS_CollisionFreeSpeedModelV3State handle) -{ - assert(handle); - const auto state = reinterpret_cast(handle); - return state->timeGap; -} - -void JPS_CollisionFreeSpeedModelV3State_SetTimeGap( - JPS_CollisionFreeSpeedModelV3State handle, - double time_gap) -{ - assert(handle); - auto state = reinterpret_cast(handle); - state->timeGap = time_gap; -} - -double JPS_CollisionFreeSpeedModelV3State_GetV0(JPS_CollisionFreeSpeedModelV3State handle) -{ - assert(handle); - const auto state = reinterpret_cast(handle); - return state->v0; -} - -void JPS_CollisionFreeSpeedModelV3State_SetV0(JPS_CollisionFreeSpeedModelV3State handle, double v0) -{ - assert(handle); - auto state = reinterpret_cast(handle); - state->v0 = v0; -} -double JPS_CollisionFreeSpeedModelV3State_GetRadius(JPS_CollisionFreeSpeedModelV3State handle) -{ - assert(handle); - const auto state = reinterpret_cast(handle); - return state->radius; -} - -void JPS_CollisionFreeSpeedModelV3State_SetRadius( - JPS_CollisionFreeSpeedModelV3State handle, - double radius) -{ - assert(handle); - auto state = reinterpret_cast(handle); - state->radius = radius; -} diff --git a/libjupedsim/src/simulation.cpp b/libjupedsim/src/simulation.cpp index 11ef5af0f..f18f6352f 100644 --- a/libjupedsim/src/simulation.cpp +++ b/libjupedsim/src/simulation.cpp @@ -283,18 +283,18 @@ JPS_AgentId JPS_Simulation_AddCollisionFreeSpeedModelV2Agent( return result.getID(); } -JPS_AgentId JPS_Simulation_AddCollisionFreeSpeedModelV3Agent( +JPS_AgentId JPS_Simulation_AddAnticipationVelocityModelAgent( JPS_Simulation handle, - JPS_CollisionFreeSpeedModelV3AgentParameters parameters, + JPS_AnticipationVelocityModelAgentParameters parameters, JPS_ErrorMessage* errorMessage) { assert(handle); auto result = GenericAgent::ID::Invalid; auto simulation = reinterpret_cast(handle); try { - if(simulation->ModelType() != OperationalModelType::COLLISION_FREE_SPEED_V3) { + if(simulation->ModelType() != OperationalModelType::ANTICIPATION_VELOCITY_MODEL) { throw std::runtime_error( - "Simulation is not configured to use Collision Free Speed Model V3"); + "Simulation is not configured to use Anticipation Velocity Model"); } GenericAgent agent( GenericAgent::ID::Invalid, @@ -302,7 +302,7 @@ JPS_AgentId JPS_Simulation_AddCollisionFreeSpeedModelV3Agent( BaseStage::ID(parameters.stageId), intoPoint(parameters.position), {}, - CollisionFreeSpeedModelV3Data{ + AnticipationVelocityModelData{ parameters.strengthNeighborRepulsion, parameters.rangeNeighborRepulsion, parameters.strengthGeometryRepulsion, @@ -518,8 +518,8 @@ JPS_ModelType JPS_Simulation_ModelType(JPS_Simulation handle) return JPS_GeneralizedCentrifugalForceModel; case OperationalModelType::COLLISION_FREE_SPEED_V2: return JPS_CollisionFreeSpeedModelV2; - case OperationalModelType::COLLISION_FREE_SPEED_V3: - return JPS_CollisionFreeSpeedModelV3; + case OperationalModelType::ANTICIPATION_VELOCITY_MODEL: + return JPS_AnticipationVelocityModel; case OperationalModelType::SOCIAL_FORCE: return JPS_SocialForceModel; } diff --git a/libsimulator/CMakeLists.txt b/libsimulator/CMakeLists.txt index ce121f816..c15cc5ad3 100644 --- a/libsimulator/CMakeLists.txt +++ b/libsimulator/CMakeLists.txt @@ -18,12 +18,12 @@ add_library(simulator STATIC src/CollisionFreeSpeedModelV2Builder.hpp src/CollisionFreeSpeedModelV2Data.hpp src/CollisionFreeSpeedModelV2Update.hpp - src/CollisionFreeSpeedModelV3.cpp - src/CollisionFreeSpeedModelV3.hpp - src/CollisionFreeSpeedModelV3Builder.cpp - src/CollisionFreeSpeedModelV3Builder.hpp - src/CollisionFreeSpeedModelV3Data.hpp - src/CollisionFreeSpeedModelV3Update.hpp + src/AnticipationVelocityModel.cpp + src/AnticipationVelocityModel.hpp + src/AnticipationVelocityModelBuilder.cpp + src/AnticipationVelocityModelBuilder.hpp + src/AnticipationVelocityModelData.hpp + src/AnticipationVelocityModelUpdate.hpp src/CollisionGeometry.cpp src/CollisionGeometry.hpp src/Ellipse.cpp diff --git a/libsimulator/src/CollisionFreeSpeedModelV3.cpp b/libsimulator/src/AnticipationVelocityModel.cpp similarity index 78% rename from libsimulator/src/CollisionFreeSpeedModelV3.cpp rename to libsimulator/src/AnticipationVelocityModel.cpp index 1990b390e..9aeaa0d03 100644 --- a/libsimulator/src/CollisionFreeSpeedModelV3.cpp +++ b/libsimulator/src/AnticipationVelocityModel.cpp @@ -1,9 +1,9 @@ // Copyright © 2012-2024 Forschungszentrum Jülich GmbH // SPDX-License-Identifier: LGPL-3.0-or-later -#include "CollisionFreeSpeedModelV3.hpp" +#include "AnticipationVelocityModel.hpp" #include -#include "CollisionFreeSpeedModelV3Data.hpp" -#include "CollisionFreeSpeedModelV3Update.hpp" +#include "AnticipationVelocityModelData.hpp" +#include "AnticipationVelocityModelUpdate.hpp" #include "GenericAgent.hpp" #include "GeometricFunctions.hpp" #include "Logger.hpp" @@ -19,12 +19,12 @@ #include #include -OperationalModelType CollisionFreeSpeedModelV3::Type() const +OperationalModelType AnticipationVelocityModel::Type() const { - return OperationalModelType::COLLISION_FREE_SPEED_V3; + return OperationalModelType::ANTICIPATION_VELOCITY_MODEL; } -OperationalModelUpdate CollisionFreeSpeedModelV3::ComputeNewPosition( +OperationalModelUpdate AnticipationVelocityModel::ComputeNewPosition( double dT, const GenericAgent& ped, const CollisionGeometry& geometry, @@ -86,26 +86,26 @@ OperationalModelUpdate CollisionFreeSpeedModelV3::ComputeNewPosition( return std::min(res, GetSpacing(ped, neighbor, direction)); }); - const auto& model = std::get(ped.model); + const auto& model = std::get(ped.model); const auto optimal_speed = OptimalSpeed(ped, spacing, model.timeGap); const auto velocity = direction * optimal_speed; - return CollisionFreeSpeedModelV3Update{ped.pos + velocity * dT, direction}; + return AnticipationVelocityModelUpdate{ped.pos + velocity * dT, direction}; }; -void CollisionFreeSpeedModelV3::ApplyUpdate(const OperationalModelUpdate& upd, GenericAgent& agent) +void AnticipationVelocityModel::ApplyUpdate(const OperationalModelUpdate& upd, GenericAgent& agent) const { - const auto& update = std::get(upd); + const auto& update = std::get(upd); agent.pos = update.position; agent.orientation = update.orientation; } -void CollisionFreeSpeedModelV3::CheckModelConstraint( +void AnticipationVelocityModel::CheckModelConstraint( const GenericAgent& agent, const NeighborhoodSearchType& neighborhoodSearch, const CollisionGeometry& geometry) const { - const auto& model = std::get(agent.model); + const auto& model = std::get(agent.model); const auto r = model.radius; constexpr double rMin = 0.; @@ -127,7 +127,7 @@ void CollisionFreeSpeedModelV3::CheckModelConstraint( if(agent.id == neighbor.id) { continue; } - const auto& neighbor_model = std::get(neighbor.model); + const auto& neighbor_model = std::get(neighbor.model); const auto contanctdDist = r + neighbor_model.radius; const auto distance = (agent.pos - neighbor.pos).Norm(); if(contanctdDist >= distance) { @@ -149,29 +149,29 @@ void CollisionFreeSpeedModelV3::CheckModelConstraint( } } -std::unique_ptr CollisionFreeSpeedModelV3::Clone() const +std::unique_ptr AnticipationVelocityModel::Clone() const { - return std::make_unique(*this); + return std::make_unique(*this); } -double CollisionFreeSpeedModelV3::OptimalSpeed( +double AnticipationVelocityModel::OptimalSpeed( const GenericAgent& ped, double spacing, double time_gap) const { - const auto& model = std::get(ped.model); - double min_spacing = -0.05; + const auto& model = std::get(ped.model); + double min_spacing = -0.1; return std::min(std::max(spacing / time_gap, min_spacing ), model.v0); } -double CollisionFreeSpeedModelV3::GetSpacing( +double AnticipationVelocityModel::GetSpacing( const GenericAgent& ped1, const GenericAgent& ped2, const Point& direction) const { - const auto& model1 = std::get(ped1.model); - const auto& model2 = std::get(ped2.model); + const auto& model1 = std::get(ped1.model); + const auto& model2 = std::get(ped2.model); const auto distp12 = ped2.pos - ped1.pos; const auto inFront = direction.ScalarProduct(distp12) >= 0; if(!inFront) { @@ -179,30 +179,31 @@ double CollisionFreeSpeedModelV3::GetSpacing( } const auto left = direction.Rotate90Deg(); + const auto private_space = 0.5; const auto l = model1.radius + model2.radius; - //std::cout << ped1.id.getID() << ": r="<< model1.radius << ", r=" << model2.radius << "\n"; // - //std::cout << ped1.pos.x << " - " << ped2.pos.x << "\n"; - float min_dist = l + 0.5;// TODO + + float min_dist = l + private_space;// TODO bool inCorridor = std::abs(left.ScalarProduct(distp12)) <= l; if(!inCorridor) { return std::numeric_limits::max(); } return distp12.Norm() - min_dist; } -Point CollisionFreeSpeedModelV3::NeighborRepulsion( +Point AnticipationVelocityModel::NeighborRepulsion( const GenericAgent& ped1, const GenericAgent& ped2) const { const auto distp12 = ped2.pos - ped1.pos; const auto [distance, direction] = distp12.NormAndNormalized(); - const auto& model1 = std::get(ped1.model); - const auto& model2 = std::get(ped2.model); + const auto& model1 = std::get(ped1.model); + const auto& model2 = std::get(ped2.model); const auto l = model1.radius + model2.radius; double seed = 42; static std::random_device rd; static std::mt19937 gen(seed); - std::uniform_real_distribution<> dis(-0.1, 0.1); // Small random values + const auto displacement = 0.1; + std::uniform_real_distribution<> dis(displacement, displacement); // Small random values Point randomVec(dis(gen), dis(gen)); @@ -216,14 +217,14 @@ Point CollisionFreeSpeedModelV3::NeighborRepulsion( // exp((l - distance) / model1.rangeNeighborRepulsion)); } -Point CollisionFreeSpeedModelV3::BoundaryRepulsion( +Point AnticipationVelocityModel::BoundaryRepulsion( const GenericAgent& ped, const LineSegment& boundary_segment) const { const auto pt = boundary_segment.ShortestPoint(ped.pos); const auto dist_vec = pt - ped.pos; const auto [dist, e_iw] = dist_vec.NormAndNormalized(); - const auto& model = std::get(ped.model); + const auto& model = std::get(ped.model); const auto l = model.radius; const auto R_iw = -model.strengthGeometryRepulsion * exp((l - dist) / model.rangeGeometryRepulsion); diff --git a/libsimulator/src/CollisionFreeSpeedModelV3.hpp b/libsimulator/src/AnticipationVelocityModel.hpp similarity index 85% rename from libsimulator/src/CollisionFreeSpeedModelV3.hpp rename to libsimulator/src/AnticipationVelocityModel.hpp index 6f84d4173..7efd2440c 100644 --- a/libsimulator/src/CollisionFreeSpeedModelV3.hpp +++ b/libsimulator/src/AnticipationVelocityModel.hpp @@ -2,15 +2,13 @@ // SPDX-License-Identifier: LGPL-3.0-or-later #pragma once -#include "CollisionFreeSpeedModelV3Data.hpp" #include "CollisionGeometry.hpp" #include "NeighborhoodSearch.hpp" #include "OperationalModel.hpp" -#include "UniqueID.hpp" struct GenericAgent; -class CollisionFreeSpeedModelV3 : public OperationalModel +class AnticipationVelocityModel : public OperationalModel { public: using NeighborhoodSearchType = NeighborhoodSearch; @@ -19,8 +17,8 @@ class CollisionFreeSpeedModelV3 : public OperationalModel double _cutOffRadius{3}; public: - CollisionFreeSpeedModelV3() = default; - ~CollisionFreeSpeedModelV3() override = default; + AnticipationVelocityModel() = default; + ~AnticipationVelocityModel() override = default; OperationalModelType Type() const override; OperationalModelUpdate ComputeNewPosition( double dT, diff --git a/libsimulator/src/AnticipationVelocityModelBuilder.cpp b/libsimulator/src/AnticipationVelocityModelBuilder.cpp new file mode 100644 index 000000000..384ae2748 --- /dev/null +++ b/libsimulator/src/AnticipationVelocityModelBuilder.cpp @@ -0,0 +1,12 @@ +// Copyright © 2012-2024 Forschungszentrum Jülich GmbH +// SPDX-License-Identifier: LGPL-3.0-or-later +#include "AnticipationVelocityModelBuilder.hpp" + +AnticipationVelocityModelBuilder::AnticipationVelocityModelBuilder() +{ +} + +AnticipationVelocityModel AnticipationVelocityModelBuilder::Build() +{ + return AnticipationVelocityModel(); +} diff --git a/libsimulator/src/AnticipationVelocityModelBuilder.hpp b/libsimulator/src/AnticipationVelocityModelBuilder.hpp new file mode 100644 index 000000000..eb4c97ca3 --- /dev/null +++ b/libsimulator/src/AnticipationVelocityModelBuilder.hpp @@ -0,0 +1,11 @@ +// Copyright © 2012-2024 Forschungszentrum Jülich GmbH +// SPDX-License-Identifier: LGPL-3.0-or-later +#pragma once + +#include "AnticipationVelocityModel.hpp" +class AnticipationVelocityModelBuilder +{ +public: + AnticipationVelocityModelBuilder(); + AnticipationVelocityModel Build(); +}; diff --git a/libsimulator/src/CollisionFreeSpeedModelV3Data.hpp b/libsimulator/src/AnticipationVelocityModelData.hpp similarity index 81% rename from libsimulator/src/CollisionFreeSpeedModelV3Data.hpp rename to libsimulator/src/AnticipationVelocityModelData.hpp index 5ab5aaf19..dc720eae0 100644 --- a/libsimulator/src/CollisionFreeSpeedModelV3Data.hpp +++ b/libsimulator/src/AnticipationVelocityModelData.hpp @@ -4,7 +4,7 @@ #include "Point.hpp" -struct CollisionFreeSpeedModelV3Data { +struct AnticipationVelocityModelData { double strengthNeighborRepulsion{}; double rangeNeighborRepulsion{}; double strengthGeometryRepulsion{}; @@ -16,16 +16,16 @@ struct CollisionFreeSpeedModelV3Data { }; template <> -struct fmt::formatter { +struct fmt::formatter { constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } template - auto format(const CollisionFreeSpeedModelV3Data& m, FormatContext& ctx) const + auto format(const AnticipationVelocityModelData& m, FormatContext& ctx) const { return fmt::format_to( ctx.out(), - "CollisionFreeSpeedModelV3[strengthNeighborRepulsion={}, " + "AnticipationVelocityModel[strengthNeighborRepulsion={}, " "rangeNeighborRepulsion={}, strengthGeometryRepulsion={}, rangeGeometryRepulsion={}, " "timeGap={}, v0={}, radius={}])", m.strengthNeighborRepulsion, diff --git a/libsimulator/src/CollisionFreeSpeedModelV3Update.hpp b/libsimulator/src/AnticipationVelocityModelUpdate.hpp similarity index 82% rename from libsimulator/src/CollisionFreeSpeedModelV3Update.hpp rename to libsimulator/src/AnticipationVelocityModelUpdate.hpp index 3eafb2aa3..678f25759 100644 --- a/libsimulator/src/CollisionFreeSpeedModelV3Update.hpp +++ b/libsimulator/src/AnticipationVelocityModelUpdate.hpp @@ -3,7 +3,7 @@ #pragma once #include "Point.hpp" -struct CollisionFreeSpeedModelV3Update { +struct AnticipationVelocityModelUpdate { Point position{}; Point orientation{}; }; diff --git a/libsimulator/src/CollisionFreeSpeedModelV3Builder.cpp b/libsimulator/src/CollisionFreeSpeedModelV3Builder.cpp deleted file mode 100644 index 5d2b9d4e1..000000000 --- a/libsimulator/src/CollisionFreeSpeedModelV3Builder.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright © 2012-2024 Forschungszentrum Jülich GmbH -// SPDX-License-Identifier: LGPL-3.0-or-later -#include "CollisionFreeSpeedModelV3Builder.hpp" - -CollisionFreeSpeedModelV3Builder::CollisionFreeSpeedModelV3Builder() -{ -} - -CollisionFreeSpeedModelV3 CollisionFreeSpeedModelV3Builder::Build() -{ - return CollisionFreeSpeedModelV3(); -} diff --git a/libsimulator/src/CollisionFreeSpeedModelV3Builder.hpp b/libsimulator/src/CollisionFreeSpeedModelV3Builder.hpp deleted file mode 100644 index 7de825f0a..000000000 --- a/libsimulator/src/CollisionFreeSpeedModelV3Builder.hpp +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright © 2012-2024 Forschungszentrum Jülich GmbH -// SPDX-License-Identifier: LGPL-3.0-or-later -#pragma once - -#include "CollisionFreeSpeedModelV3.hpp" -class CollisionFreeSpeedModelV3Builder -{ -public: - CollisionFreeSpeedModelV3Builder(); - CollisionFreeSpeedModelV3 Build(); -}; diff --git a/libsimulator/src/GenericAgent.hpp b/libsimulator/src/GenericAgent.hpp index 61faf19c9..5857ef307 100644 --- a/libsimulator/src/GenericAgent.hpp +++ b/libsimulator/src/GenericAgent.hpp @@ -3,7 +3,7 @@ #pragma once #include "CollisionFreeSpeedModelData.hpp" #include "CollisionFreeSpeedModelV2Data.hpp" -#include "CollisionFreeSpeedModelV3Data.hpp" +#include "AnticipationVelocityModelData.hpp" #include "GeneralizedCentrifugalForceModelData.hpp" #include "OperationalModel.hpp" #include "Point.hpp" @@ -34,7 +34,7 @@ struct GenericAgent { GeneralizedCentrifugalForceModelData, CollisionFreeSpeedModelData, CollisionFreeSpeedModelV2Data, - CollisionFreeSpeedModelV3Data, + AnticipationVelocityModelData, SocialForceModelData>; Model model{}; diff --git a/libsimulator/src/OperationalModelType.hpp b/libsimulator/src/OperationalModelType.hpp index e85e45099..7343d815f 100644 --- a/libsimulator/src/OperationalModelType.hpp +++ b/libsimulator/src/OperationalModelType.hpp @@ -6,6 +6,6 @@ enum class OperationalModelType { COLLISION_FREE_SPEED, GENERALIZED_CENTRIFUGAL_FORCE, COLLISION_FREE_SPEED_V2, - COLLISION_FREE_SPEED_V3, + ANTICIPATION_VELOCITY_MODEL, SOCIAL_FORCE }; diff --git a/libsimulator/src/OperationalModelUpdate.hpp b/libsimulator/src/OperationalModelUpdate.hpp index ecedffc13..6f949947b 100644 --- a/libsimulator/src/OperationalModelUpdate.hpp +++ b/libsimulator/src/OperationalModelUpdate.hpp @@ -1,8 +1,8 @@ // Copyright © 2012-2024 Forschungszentrum Jülich GmbH // SPDX-License-Identifier: LGPL-3.0-or-later +#include "AnticipationVelocityModelUpdate.hpp" #include "CollisionFreeSpeedModelUpdate.hpp" #include "CollisionFreeSpeedModelV2Update.hpp" -#include "CollisionFreeSpeedModelV3Update.hpp" #include "GeneralizedCentrifugalForceModelUpdate.hpp" #include "SocialForceModelUpdate.hpp" @@ -12,5 +12,5 @@ using OperationalModelUpdate = std::variant< GeneralizedCentrifugalForceModelUpdate, CollisionFreeSpeedModelUpdate, CollisionFreeSpeedModelV2Update, - CollisionFreeSpeedModelV3Update, + AnticipationVelocityModelUpdate, SocialForceModelUpdate>; diff --git a/python_bindings_jupedsim/CMakeLists.txt b/python_bindings_jupedsim/CMakeLists.txt index 288a70039..2b9e1beae 100644 --- a/python_bindings_jupedsim/CMakeLists.txt +++ b/python_bindings_jupedsim/CMakeLists.txt @@ -6,7 +6,7 @@ add_library(py_jupedsim MODULE generalized_centrifugal_force_model.cpp collision_free_speed_model.cpp collision_free_speed_model_v2.cpp - collision_free_speed_model_v3.cpp + anticipation_velocity_model.cpp social_force_model.cpp logging.cpp logging.hpp diff --git a/python_bindings_jupedsim/agent.cpp b/python_bindings_jupedsim/agent.cpp index 95c36ac6f..bfd6f1a2c 100644 --- a/python_bindings_jupedsim/agent.cpp +++ b/python_bindings_jupedsim/agent.cpp @@ -70,7 +70,7 @@ void init_agent(py::module_& m) std::unique_ptr, std::unique_ptr, std::unique_ptr, - std::unique_ptr, + std::unique_ptr, std::unique_ptr> { switch(JPS_Agent_GetModelType(w.handle)) { case JPS_GeneralizedCentrifugalForceModel: @@ -82,9 +82,9 @@ void init_agent(py::module_& m) case JPS_CollisionFreeSpeedModelV2: return std::make_unique( JPS_Agent_GetCollisionFreeSpeedModelV2State(w.handle, nullptr)); - case JPS_CollisionFreeSpeedModelV3: - return std::make_unique( - JPS_Agent_GetCollisionFreeSpeedModelV3State(w.handle, nullptr)); + case JPS_AnticipationVelocityModel: + return std::make_unique( + JPS_Agent_GetAnticipationVelocityModelState(w.handle, nullptr)); case JPS_SocialForceModel: return std::make_unique( JPS_Agent_GetSocialForceModelState(w.handle, nullptr)); diff --git a/python_bindings_jupedsim/collision_free_speed_model_v3.cpp b/python_bindings_jupedsim/anticipation_velocity_model.cpp similarity index 60% rename from python_bindings_jupedsim/collision_free_speed_model_v3.cpp rename to python_bindings_jupedsim/anticipation_velocity_model.cpp index f81a8834f..75e7bf7af 100644 --- a/python_bindings_jupedsim/collision_free_speed_model_v3.cpp +++ b/python_bindings_jupedsim/anticipation_velocity_model.cpp @@ -1,6 +1,6 @@ // Copyright © 2012-2024 Forschungszentrum Jülich GmbH // SPDX-License-Identifier: LGPL-3.0-or-later -#include "jupedsim/collision_free_speed_model_v3.h" +#include "jupedsim/anticipation_velocity_model.h" #include "conversion.hpp" #include "wrapper.hpp" @@ -13,10 +13,10 @@ namespace py = pybind11; -void init_collision_free_speed_model_v3(py::module_& m) +void init_anticipation_velocity_model(py::module_& m) { - py::class_( - m, "CollisionFreeSpeedModelV3AgentParameters") + py::class_( + m, "AnticipationVelocityModelAgentParameters") .def( py::init([](std::tuple position, double time_gap, @@ -28,7 +28,7 @@ void init_collision_free_speed_model_v3(py::module_& m) double rangeNeighborRepulsion, double strengthGeometryRepulsion, double rangeGeometryRepulsion) { - return JPS_CollisionFreeSpeedModelV3AgentParameters{ + return JPS_AnticipationVelocityModelAgentParameters{ intoJPS_Point(position), journey_id, stage_id, @@ -51,7 +51,7 @@ void init_collision_free_speed_model_v3(py::module_& m) py::arg("range_neighbor_repulsion"), py::arg("strength_geometry_repulsion"), py::arg("range_geometry_repulsion")) - .def("__repr__", [](const JPS_CollisionFreeSpeedModelV3AgentParameters& p) { + .def("__repr__", [](const JPS_AnticipationVelocityModelAgentParameters& p) { return fmt::format( "position: {}, journey_id: {}, stage_id: {}, " "time_gap: {}, v0: {}, radius: {}", @@ -68,14 +68,14 @@ void init_collision_free_speed_model_v3(py::module_& m) p.strengthGeometryRepulsion, p.rangeGeometryRepulsion); }); - py::class_(m, "CollisionFreeSpeedModelV3Builder") + py::class_(m, "AnticipationVelocityModelBuilder") .def(py::init([]() { - return std::make_unique( - JPS_CollisionFreeSpeedModelV3Builder_Create()); + return std::make_unique( + JPS_AnticipationVelocityModelBuilder_Create()); })) - .def("build", [](JPS_CollisionFreeSpeedModelV3Builder_Wrapper& w) { + .def("build", [](JPS_AnticipationVelocityModelBuilder_Wrapper& w) { JPS_ErrorMessage errorMsg{}; - auto result = JPS_CollisionFreeSpeedModelV3Builder_Build(w.handle, &errorMsg); + auto result = JPS_AnticipationVelocityModelBuilder_Build(w.handle, &errorMsg); if(result) { return std::make_unique(result); } @@ -83,65 +83,65 @@ void init_collision_free_speed_model_v3(py::module_& m) JPS_ErrorMessage_Free(errorMsg); throw std::runtime_error{msg}; }); - py::class_(m, "CollisionFreeSpeedModelV3State") + py::class_(m, "AnticipationVelocityModelState") .def_property( "time_gap", - [](const JPS_CollisionFreeSpeedModelV3State_Wrapper& w) { - return JPS_CollisionFreeSpeedModelV3State_GetTimeGap(w.handle); + [](const JPS_AnticipationVelocityModelState_Wrapper& w) { + return JPS_AnticipationVelocityModelState_GetTimeGap(w.handle); }, - [](JPS_CollisionFreeSpeedModelV3State_Wrapper& w, double time_gap) { - JPS_CollisionFreeSpeedModelV3State_SetTimeGap(w.handle, time_gap); + [](JPS_AnticipationVelocityModelState_Wrapper& w, double time_gap) { + JPS_AnticipationVelocityModelState_SetTimeGap(w.handle, time_gap); }) .def_property( "v0", - [](const JPS_CollisionFreeSpeedModelV3State_Wrapper& w) { - return JPS_CollisionFreeSpeedModelV3State_GetV0(w.handle); + [](const JPS_AnticipationVelocityModelState_Wrapper& w) { + return JPS_AnticipationVelocityModelState_GetV0(w.handle); }, - [](JPS_CollisionFreeSpeedModelV3State_Wrapper& w, double v0) { - JPS_CollisionFreeSpeedModelV3State_SetV0(w.handle, v0); + [](JPS_AnticipationVelocityModelState_Wrapper& w, double v0) { + JPS_AnticipationVelocityModelState_SetV0(w.handle, v0); }) .def_property( "radius", - [](const JPS_CollisionFreeSpeedModelV3State_Wrapper& w) { - return JPS_CollisionFreeSpeedModelV3State_GetRadius(w.handle); + [](const JPS_AnticipationVelocityModelState_Wrapper& w) { + return JPS_AnticipationVelocityModelState_GetRadius(w.handle); }, - [](JPS_CollisionFreeSpeedModelV3State_Wrapper& w, double radius) { - JPS_CollisionFreeSpeedModelV3State_SetRadius(w.handle, radius); + [](JPS_AnticipationVelocityModelState_Wrapper& w, double radius) { + JPS_AnticipationVelocityModelState_SetRadius(w.handle, radius); }) .def_property( "strength_neighbor_repulsion", - [](const JPS_CollisionFreeSpeedModelV3State_Wrapper& w) { - return JPS_CollisionFreeSpeedModelV3State_GetStrengthNeighborRepulsion(w.handle); + [](const JPS_AnticipationVelocityModelState_Wrapper& w) { + return JPS_AnticipationVelocityModelState_GetStrengthNeighborRepulsion(w.handle); }, - [](JPS_CollisionFreeSpeedModelV3State_Wrapper& w, double strengthNeighborRepulsion) { - JPS_CollisionFreeSpeedModelV3State_SetStrengthNeighborRepulsion( + [](JPS_AnticipationVelocityModelState_Wrapper& w, double strengthNeighborRepulsion) { + JPS_AnticipationVelocityModelState_SetStrengthNeighborRepulsion( w.handle, strengthNeighborRepulsion); }) .def_property( "range_neighbor_repulsion", - [](const JPS_CollisionFreeSpeedModelV3State_Wrapper& w) { - return JPS_CollisionFreeSpeedModelV3State_GetRangeNeighborRepulsion(w.handle); + [](const JPS_AnticipationVelocityModelState_Wrapper& w) { + return JPS_AnticipationVelocityModelState_GetRangeNeighborRepulsion(w.handle); }, - [](JPS_CollisionFreeSpeedModelV3State_Wrapper& w, double rangeNeighborRepulsion) { - JPS_CollisionFreeSpeedModelV3State_SetRangeNeighborRepulsion( + [](JPS_AnticipationVelocityModelState_Wrapper& w, double rangeNeighborRepulsion) { + JPS_AnticipationVelocityModelState_SetRangeNeighborRepulsion( w.handle, rangeNeighborRepulsion); }) .def_property( "strength_geometry_repulsion", - [](const JPS_CollisionFreeSpeedModelV3State_Wrapper& w) { - return JPS_CollisionFreeSpeedModelV3State_GetStrengthGeometryRepulsion(w.handle); + [](const JPS_AnticipationVelocityModelState_Wrapper& w) { + return JPS_AnticipationVelocityModelState_GetStrengthGeometryRepulsion(w.handle); }, - [](JPS_CollisionFreeSpeedModelV3State_Wrapper& w, double strengthGeometryRepulsion) { - JPS_CollisionFreeSpeedModelV3State_SetStrengthGeometryRepulsion( + [](JPS_AnticipationVelocityModelState_Wrapper& w, double strengthGeometryRepulsion) { + JPS_AnticipationVelocityModelState_SetStrengthGeometryRepulsion( w.handle, strengthGeometryRepulsion); }) .def_property( "range_geometry_repulsion", - [](const JPS_CollisionFreeSpeedModelV3State_Wrapper& w) { - return JPS_CollisionFreeSpeedModelV3State_GetRangeGeometryRepulsion(w.handle); + [](const JPS_AnticipationVelocityModelState_Wrapper& w) { + return JPS_AnticipationVelocityModelState_GetRangeGeometryRepulsion(w.handle); }, - [](JPS_CollisionFreeSpeedModelV3State_Wrapper& w, double rangeGeometryRepulsion) { - JPS_CollisionFreeSpeedModelV3State_SetRangeGeometryRepulsion( + [](JPS_AnticipationVelocityModelState_Wrapper& w, double rangeGeometryRepulsion) { + JPS_AnticipationVelocityModelState_SetRangeGeometryRepulsion( w.handle, rangeGeometryRepulsion); }); } diff --git a/python_bindings_jupedsim/bindings_jupedsim.cpp b/python_bindings_jupedsim/bindings_jupedsim.cpp index 3784ef6d6..68aa8b283 100644 --- a/python_bindings_jupedsim/bindings_jupedsim.cpp +++ b/python_bindings_jupedsim/bindings_jupedsim.cpp @@ -10,7 +10,7 @@ void init_trace(py::module_& m); void init_generalized_centrifugal_force_model(py::module_& m); void init_collision_free_speed_model(py::module_& m); void init_collision_free_speed_model_v2(py::module_& m); -void init_collision_free_speed_model_v3(py::module_& m); +void init_anticipation_velocity_model(py::module_& m); void init_social_force_model(py::module_& m); void init_geometry(py::module_& m); void init_routing(py::module_& m); @@ -28,7 +28,7 @@ PYBIND11_MODULE(py_jupedsim, m) init_generalized_centrifugal_force_model(m); init_collision_free_speed_model(m); init_collision_free_speed_model_v2(m); - init_collision_free_speed_model_v3(m); + init_anticipation_velocity_model(m); init_social_force_model(m); init_geometry(m); init_routing(m); diff --git a/python_bindings_jupedsim/simulation.cpp b/python_bindings_jupedsim/simulation.cpp index 39075c505..8c6fda9ac 100644 --- a/python_bindings_jupedsim/simulation.cpp +++ b/python_bindings_jupedsim/simulation.cpp @@ -159,9 +159,9 @@ void init_simulation(py::module_& m) .def( "add_agent", [](JPS_Simulation_Wrapper& simulation, - JPS_CollisionFreeSpeedModelV3AgentParameters& parameters) { + JPS_AnticipationVelocityModelAgentParameters& parameters) { JPS_ErrorMessage errorMsg{}; - auto result = JPS_Simulation_AddCollisionFreeSpeedModelV3Agent( + auto result = JPS_Simulation_AddAnticipationVelocityModelAgent( simulation.handle, parameters, &errorMsg); if(result) { return result; diff --git a/python_bindings_jupedsim/wrapper.hpp b/python_bindings_jupedsim/wrapper.hpp index 9e88ff3af..8369f0221 100644 --- a/python_bindings_jupedsim/wrapper.hpp +++ b/python_bindings_jupedsim/wrapper.hpp @@ -1,6 +1,7 @@ // Copyright © 2012-2024 Forschungszentrum Jülich GmbH // SPDX-License-Identifier: LGPL-3.0-or-later #pragma once +#include "jupedsim/anticipation_velocity_model.h" #include #define OWNED_WRAPPER(cls) \ @@ -38,7 +39,7 @@ OWNED_WRAPPER(JPS_GeometryBuilder); OWNED_WRAPPER(JPS_OperationalModel); OWNED_WRAPPER(JPS_CollisionFreeSpeedModelBuilder); OWNED_WRAPPER(JPS_CollisionFreeSpeedModelV2Builder); -OWNED_WRAPPER(JPS_CollisionFreeSpeedModelV3Builder); +OWNED_WRAPPER(JPS_AnticipationVelocityModelBuilder); OWNED_WRAPPER(JPS_GeneralizedCentrifugalForceModelBuilder); OWNED_WRAPPER(JPS_SocialForceModelBuilder); OWNED_WRAPPER(JPS_JourneyDescription); @@ -56,5 +57,5 @@ WRAPPER(JPS_Agent); WRAPPER(JPS_GeneralizedCentrifugalForceModelState); WRAPPER(JPS_CollisionFreeSpeedModelState); WRAPPER(JPS_CollisionFreeSpeedModelV2State); -WRAPPER(JPS_CollisionFreeSpeedModelV3State); +WRAPPER(JPS_AnticipationVelocityModelState); WRAPPER(JPS_SocialForceModelState); diff --git a/python_modules/jupedsim/jupedsim/__init__.py b/python_modules/jupedsim/jupedsim/__init__.py index d313a39de..e607badef 100644 --- a/python_modules/jupedsim/jupedsim/__init__.py +++ b/python_modules/jupedsim/jupedsim/__init__.py @@ -35,10 +35,10 @@ CollisionFreeSpeedModelV2AgentParameters, CollisionFreeSpeedModelV2State, ) -from jupedsim.models.collision_free_speed_v3 import ( - CollisionFreeSpeedModelV3, - CollisionFreeSpeedModelV3AgentParameters, - CollisionFreeSpeedModelV3State, +from jupedsim.models.anticipation_velocity_model import ( + AnticipationVelocityModel, + AnticipationVelocityModelAgentParameters, + AnticipationVelocityModelState, ) from jupedsim.models.generalized_centrifugal_force import ( @@ -111,9 +111,9 @@ "CollisionFreeSpeedModelV2AgentParameters", "CollisionFreeSpeedModelV2", "CollisionFreeSpeedModelV2State", - "CollisionFreeSpeedModelV3AgentParameters", - "CollisionFreeSpeedModelV3", - "CollisionFreeSpeedModelV3State", + "AnticipationVelocityModelAgentParameters", + "AnticipationVelocityModel", + "AnticipationVelocityModelState", "SocialForceModelAgentParameters", "SocialForceModel", "SocialForceModelState", diff --git a/python_modules/jupedsim/jupedsim/agent.py b/python_modules/jupedsim/jupedsim/agent.py index 136731cba..0aacae917 100644 --- a/python_modules/jupedsim/jupedsim/agent.py +++ b/python_modules/jupedsim/jupedsim/agent.py @@ -6,8 +6,8 @@ from jupedsim.models.collision_free_speed_v2 import ( CollisionFreeSpeedModelV2State, ) -from jupedsim.models.collision_free_speed_v3 import ( - CollisionFreeSpeedModelV3State, +from jupedsim.models.anticipation_velocity_model import ( + AnticipationVelocityModelState, ) from jupedsim.models.generalized_centrifugal_force import ( GeneralizedCentrifugalForceModelState, @@ -108,6 +108,7 @@ def model( ) -> ( GeneralizedCentrifugalForceModelState | CollisionFreeSpeedModelState + | AnticipationVelocityModelState | SocialForceModelState ): """Access model specific state of this agent.""" @@ -118,8 +119,8 @@ def model( return CollisionFreeSpeedModelState(model) elif isinstance(model, py_jps.CollisionFreeSpeedModelV2State): return CollisionFreeSpeedModelV2State(model) - elif isinstance(model, py_jps.CollisionFreeSpeedModelV3State): - return CollisionFreeSpeedModelV3State(model) + elif isinstance(model, py_jps.AnticipationVelocityModelState): + return AnticipationVelocityModelState(model) elif isinstance(model, py_jps.SocialForceModelState): return SocialForceModelState(model) else: diff --git a/python_modules/jupedsim/jupedsim/models/collision_free_speed_v3.py b/python_modules/jupedsim/jupedsim/models/anticipation_velocity_model.py similarity index 76% rename from python_modules/jupedsim/jupedsim/models/collision_free_speed_v3.py rename to python_modules/jupedsim/jupedsim/models/anticipation_velocity_model.py index fc1688976..0d4bf7a68 100644 --- a/python_modules/jupedsim/jupedsim/models/collision_free_speed_v3.py +++ b/python_modules/jupedsim/jupedsim/models/anticipation_velocity_model.py @@ -7,28 +7,37 @@ @dataclass(kw_only=True) -class CollisionFreeSpeedModelV3: - """Collision Free Speed Model V3 +class AnticipationVelocityModel: + """Anticipation Velocity Model (AVM). - This is a variation of the Collision Free Speed Model where geometry and neighbor repulsion are individual - agent parameters instead of global parameters. + The AVM incorporates pedestrian anticipation, divided into three phases: + 1. Perception of the current situation. + 2. Prediction of future situations. + 3. Strategy selection leading to action. - A general description of the Collision Free Speed Model can be found in the originating publication - https://arxiv.org/abs/1512.05597 + This model quantitatively reproduces bidirectional pedestrian flow by accounting for: + - Anticipation of changes in neighboring pedestrians' positions. + - The strategy of following others' movement. The AVM is a model that takes into consideration + the anticipation of pedestrians. For this, the process of anticipation is divided into three parts: + - perception of the actual situation, + - prediction of a future situation and + - selection of a strategy leading to action. - A more detailed description can be found at https://pedestriandynamics.org/models/collision_free_speed_model/ + + A general description of the AVM can be found in the originating publication + https://doi.org/10.1016/j.trc.2021.103464 """ pass @dataclass(kw_only=True) -class CollisionFreeSpeedModelV3AgentParameters: +class AnticipationVelocityModelAgentParameters: """ - Agent parameters for Collision Free Speed Model V3. + Agent parameters for Anticipation Velocity Model (AVM). - See the scientific publication for more details about this model - https://arxiv.org/abs/1512.05597 + See publication for more details about this model + https://doi.org/10.1016/j.trc.2021.103464 .. note:: @@ -40,7 +49,7 @@ class CollisionFreeSpeedModelV3AgentParameters: .. code:: python positions = [...] # List of initial agent positions - params = CollisionFreeSpeedModelV3AgentParameters(v0=0.9) # all agents are slower + params = AnticipationVelocityModelAgentParameters(v0=0.9) # all agents are slower for p in positions: params.position = p sim.add_agent(params) @@ -71,8 +80,8 @@ class CollisionFreeSpeedModelV3AgentParameters: def as_native( self, - ) -> py_jps.CollisionFreeSpeedModelV3AgentParameters: - return py_jps.CollisionFreeSpeedModelV3AgentParameters( + ) -> py_jps.AnticipationVelocityModelAgentParameters: + return py_jps.AnticipationVelocityModelAgentParameters( position=self.position, time_gap=self.time_gap, v0=self.v0, @@ -86,7 +95,7 @@ def as_native( ) -class CollisionFreeSpeedModelV3State: +class AnticipationVelocityModelState: def __init__(self, backing): self._obj = backing diff --git a/python_modules/jupedsim/jupedsim/simulation.py b/python_modules/jupedsim/jupedsim/simulation.py index ddb9415db..b401d28e0 100644 --- a/python_modules/jupedsim/jupedsim/simulation.py +++ b/python_modules/jupedsim/jupedsim/simulation.py @@ -19,9 +19,9 @@ CollisionFreeSpeedModelV2, CollisionFreeSpeedModelV2AgentParameters, ) -from jupedsim.models.collision_free_speed_v3 import ( - CollisionFreeSpeedModelV3, - CollisionFreeSpeedModelV3AgentParameters, +from jupedsim.models.anticipation_velocity_model import ( + AnticipationVelocityModel, + AnticipationVelocityModelAgentParameters, ) from jupedsim.models.generalized_centrifugal_force import ( GeneralizedCentrifugalForceModel, @@ -57,7 +57,7 @@ def __init__( CollisionFreeSpeedModel | GeneralizedCentrifugalForceModel | CollisionFreeSpeedModelV2 - | CollisionFreeSpeedModelV3 + | AnticipationVelocityModel | SocialForceModel ), geometry: ( @@ -115,8 +115,8 @@ def __init__( elif isinstance(model, CollisionFreeSpeedModelV2): model_builder = py_jps.CollisionFreeSpeedModelV2Builder() py_jps_model = model_builder.build() - elif isinstance(model, CollisionFreeSpeedModelV3): - model_builder = py_jps.CollisionFreeSpeedModelV3Builder() + elif isinstance(model, AnticipationVelocityModel): + model_builder = py_jps.AnticipationVelocityModelBuilder() py_jps_model = model_builder.build() elif isinstance(model, GeneralizedCentrifugalForceModel): model_builder = py_jps.GeneralizedCentrifugalForceModelBuilder( @@ -256,7 +256,7 @@ def add_agent( GeneralizedCentrifugalForceModelAgentParameters | CollisionFreeSpeedModelAgentParameters | CollisionFreeSpeedModelV2AgentParameters - | CollisionFreeSpeedModelV3AgentParameters + | AnticipationVelocityModelAgentParameters | SocialForceModelAgentParameters ), ) -> int: diff --git a/systemtest/test_model_properties.py b/systemtest/test_model_properties.py index 5da3dd9b1..609da4cf2 100644 --- a/systemtest/test_model_properties.py +++ b/systemtest/test_model_properties.py @@ -84,21 +84,21 @@ def test_set_model_parameters_collision_free_speed_model_v2( @pytest.fixture -def simulation_with_collision_free_speed_model_v3(): +def simulation_with_anticipation_velocity_model(): return jps.Simulation( - model=jps.CollisionFreeSpeedModelV3(), + model=jps.AnticipationVelocityModel(), geometry=[(0, 0), (10, 0), (10, 10), (0, 10)], ) -def test_set_model_parameters_collision_free_speed_model_v3( - simulation_with_collision_free_speed_model_v3, +def test_set_model_parameters_anticipation_velocity_model( + simulation_with_anticipation_velocity_model, ): - sim = simulation_with_collision_free_speed_model_v3 + sim = simulation_with_anticipation_velocity_model wp = sim.add_waypoint_stage((10, 1), 0.5) journey_id = sim.add_journey(jps.JourneyDescription([wp])) - agent = jps.CollisionFreeSpeedModelV3AgentParameters( + agent = jps.AnticipationVelocityModelAgentParameters( journey_id=journey_id, stage_id=wp, position=(1, 1), From f2344d98e6254f07d30ca27c1e209b3936a84358 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Fri, 3 Jan 2025 13:51:58 +0100 Subject: [PATCH 06/52] remove unused imports --- libsimulator/src/AnticipationVelocityModel.cpp | 4 ---- libsimulator/src/OperationalModel.hpp | 3 --- 2 files changed, 7 deletions(-) diff --git a/libsimulator/src/AnticipationVelocityModel.cpp b/libsimulator/src/AnticipationVelocityModel.cpp index 9aeaa0d03..40169213f 100644 --- a/libsimulator/src/AnticipationVelocityModel.cpp +++ b/libsimulator/src/AnticipationVelocityModel.cpp @@ -6,12 +6,8 @@ #include "AnticipationVelocityModelUpdate.hpp" #include "GenericAgent.hpp" #include "GeometricFunctions.hpp" -#include "Logger.hpp" -#include "Mathematics.hpp" -#include "NeighborhoodSearch.hpp" #include "OperationalModel.hpp" #include "SimulationError.hpp" -#include "Stage.hpp" #include #include diff --git a/libsimulator/src/OperationalModel.hpp b/libsimulator/src/OperationalModel.hpp index 13402d9a3..4d61de642 100644 --- a/libsimulator/src/OperationalModel.hpp +++ b/libsimulator/src/OperationalModel.hpp @@ -4,15 +4,12 @@ #include "Clonable.hpp" #include "CollisionGeometry.hpp" -#include "GeneralizedCentrifugalForceModelData.hpp" #include "OperationalModelType.hpp" #include "OperationalModelUpdate.hpp" #include "Point.hpp" #include "SimulationError.hpp" -#include "UniqueID.hpp" #include -#include template class NeighborhoodSearch; From b7e4218ff9dab41c2156e60c6b1528bc9d8e59fd Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Mon, 6 Jan 2025 15:22:32 +0100 Subject: [PATCH 07/52] Implement direction of agents --- .../src/AnticipationVelocityModel.cpp | 66 ++++++++++++++----- .../src/AnticipationVelocityModel.hpp | 4 +- .../src/AnticipationVelocityModelData.hpp | 13 ++-- .../src/AnticipationVelocityModelUpdate.hpp | 1 + libsimulator/src/Point.cpp | 5 ++ libsimulator/src/Point.hpp | 3 +- 6 files changed, 69 insertions(+), 23 deletions(-) diff --git a/libsimulator/src/AnticipationVelocityModel.cpp b/libsimulator/src/AnticipationVelocityModel.cpp index 40169213f..a1992cd70 100644 --- a/libsimulator/src/AnticipationVelocityModel.cpp +++ b/libsimulator/src/AnticipationVelocityModel.cpp @@ -8,7 +8,7 @@ #include "GeometricFunctions.hpp" #include "OperationalModel.hpp" #include "SimulationError.hpp" - +#include "Macros.hpp" #include #include #include @@ -185,32 +185,64 @@ double AnticipationVelocityModel::GetSpacing( } return distp12.Norm() - min_dist; } + +Point AnticipationVelocityModel::CalculateInfluenceDirection(const Point& desiredDirection, const Point& predictedDirection) const +{ + // Eq. (5) + const double seed = 42; + static std::random_device rd; + static std::mt19937 gen(seed); + static std::uniform_int_distribution dist(0, 1); // Random integers: 0 or 1 + + Point orthogonalDirection = Point(-desiredDirection.y, desiredDirection.x).Normalized(); + double alignment = orthogonalDirection.ScalarProduct(predictedDirection); + Point influenceDirection = orthogonalDirection; + if (fabs(alignment) < J_EPS) { + // Choose a random direction (left or right) + if (dist(gen) % 2 == 0) { + influenceDirection = -orthogonalDirection; + } + } else if (alignment > 0) { + influenceDirection = -orthogonalDirection; + } + return influenceDirection; +} + Point AnticipationVelocityModel::NeighborRepulsion( const GenericAgent& ped1, const GenericAgent& ped2) const { - const auto distp12 = ped2.pos - ped1.pos; - const auto [distance, direction] = distp12.NormAndNormalized(); const auto& model1 = std::get(ped1.model); const auto& model2 = std::get(ped2.model); - - const auto l = model1.radius + model2.radius; - double seed = 42; - static std::random_device rd; - static std::mt19937 gen(seed); - const auto displacement = 0.1; - std::uniform_real_distribution<> dis(displacement, displacement); // Small random values - Point randomVec(dis(gen), dis(gen)); + const auto distp12 = ped2.pos - ped1.pos; + const auto [distance, ep12] = distp12.NormAndNormalized(); + const double adjustedDist = distance - (model1.radius + model2.radius); + + // Pedestrian movement and desired directions + const auto& e1 = ped1.orientation; + const auto& d1 = (ped1.destination - ped1.pos).Normalized(); + const auto& e2 = ped2.orientation; + + // Check perception range (Eq. 1) + const auto inPerceptionRange = d1.ScalarProduct(ep12) >= 0 || e1.ScalarProduct(ep12) >= 0; + if(!inPerceptionRange) return Point(0, 0); + + double S_Gap = (model1.velocity - model2.velocity).ScalarProduct(ep12) * model1.anticipationTime; + double R_dist = adjustedDist - S_Gap; + R_dist = std::max(R_dist, 0.0); // Clamp to zero if negative - auto randomizedDirection = (direction + randomVec).Normalized(); - return randomizedDirection * -(model1.strengthNeighborRepulsion * - exp((l - distance) / model1.rangeNeighborRepulsion)); + // Interaction strength (Eq. 3 & 4) + constexpr double alignmentBase = 1.0; + constexpr double alignmentWeight = 0.5; + const double alignmentFactor = alignmentBase + alignmentWeight * (1.0 - d1.ScalarProduct(e2)); + const double interactionStrength = model1.strengthNeighborRepulsion * alignmentFactor * std::exp(-R_dist/model1.rangeNeighborRepulsion); + auto newep12 = distp12 + model2.velocity*model2.anticipationTime ; //e_ij(t+ta) + // Compute adjusted influence direction + const auto influenceDirection = CalculateInfluenceDirection(d1, newep12); + return influenceDirection * interactionStrength; - - // return direction * -(model1.strengthNeighborRepulsion * - // exp((l - distance) / model1.rangeNeighborRepulsion)); } Point AnticipationVelocityModel::BoundaryRepulsion( diff --git a/libsimulator/src/AnticipationVelocityModel.hpp b/libsimulator/src/AnticipationVelocityModel.hpp index 7efd2440c..0b6d0cf05 100644 --- a/libsimulator/src/AnticipationVelocityModel.hpp +++ b/libsimulator/src/AnticipationVelocityModel.hpp @@ -33,7 +33,9 @@ class AnticipationVelocityModel : public OperationalModel std::unique_ptr Clone() const override; private: - double OptimalSpeed(const GenericAgent& ped, double spacing, double time_gap) const; + double OptimalSpeed(const GenericAgent& ped, double spacing, double time_gap) + const; + Point CalculateInfluenceDirection(const Point& desiredDirection, const Point& predictedDirection) const; double GetSpacing(const GenericAgent& ped1, const GenericAgent& ped2, const Point& direction) const; Point NeighborRepulsion(const GenericAgent& ped1, const GenericAgent& ped2) const; diff --git a/libsimulator/src/AnticipationVelocityModelData.hpp b/libsimulator/src/AnticipationVelocityModelData.hpp index dc720eae0..fe05d131d 100644 --- a/libsimulator/src/AnticipationVelocityModelData.hpp +++ b/libsimulator/src/AnticipationVelocityModelData.hpp @@ -9,8 +9,10 @@ struct AnticipationVelocityModelData { double rangeNeighborRepulsion{}; double strengthGeometryRepulsion{}; double rangeGeometryRepulsion{}; - - double timeGap{1}; + double anticipationTime{1.0}; // t^a + double reactionTime{0.3}; // tau + Point velocity{}; // v + double timeGap{1.06}; double v0{1.2}; double radius{0.15}; }; @@ -27,13 +29,16 @@ struct fmt::formatter { ctx.out(), "AnticipationVelocityModel[strengthNeighborRepulsion={}, " "rangeNeighborRepulsion={}, strengthGeometryRepulsion={}, rangeGeometryRepulsion={}, " - "timeGap={}, v0={}, radius={}])", + "timeGap={}, v0={}, radius={}, reactionTime={}, anticipationTime={}, velocity={}])", m.strengthNeighborRepulsion, m.rangeNeighborRepulsion, m.strengthGeometryRepulsion, m.rangeGeometryRepulsion, m.timeGap, m.v0, - m.radius); + m.radius, + m.reactionTime, + m.anticipationTime, + m.velocity); } }; diff --git a/libsimulator/src/AnticipationVelocityModelUpdate.hpp b/libsimulator/src/AnticipationVelocityModelUpdate.hpp index 678f25759..f3c7396c0 100644 --- a/libsimulator/src/AnticipationVelocityModelUpdate.hpp +++ b/libsimulator/src/AnticipationVelocityModelUpdate.hpp @@ -5,5 +5,6 @@ struct AnticipationVelocityModelUpdate { Point position{}; + Point velocity{}; Point orientation{}; }; diff --git a/libsimulator/src/Point.cpp b/libsimulator/src/Point.cpp index 05fa67599..bbb0e7ba0 100644 --- a/libsimulator/src/Point.cpp +++ b/libsimulator/src/Point.cpp @@ -169,6 +169,11 @@ Point& Point::operator+=(const Point& p) return *this; } +Point Point::operator-() const +{ + return Point(-x, -y); +} + const Point operator/(const Point& p, double f) { static auto constexpr eps = diff --git a/libsimulator/src/Point.hpp b/libsimulator/src/Point.hpp index d682d832c..b0a1d112c 100644 --- a/libsimulator/src/Point.hpp +++ b/libsimulator/src/Point.hpp @@ -63,7 +63,8 @@ class Point bool operator!=(const Point& p) const; /// Assignement Point& operator+=(const Point& p); - + /// unary negation operator + Point operator-() const; bool operator<(const Point& rhs) const; bool operator>(const Point& rhs) const; From 9c6b3651bd37fb26dcedb21685057ddb6c02f7e7 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Mon, 6 Jan 2025 15:39:43 +0100 Subject: [PATCH 08/52] Implement boundaryRepulsion --- .../src/AnticipationVelocityModel.cpp | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/libsimulator/src/AnticipationVelocityModel.cpp b/libsimulator/src/AnticipationVelocityModel.cpp index a1992cd70..12606d014 100644 --- a/libsimulator/src/AnticipationVelocityModel.cpp +++ b/libsimulator/src/AnticipationVelocityModel.cpp @@ -247,14 +247,23 @@ Point AnticipationVelocityModel::NeighborRepulsion( Point AnticipationVelocityModel::BoundaryRepulsion( const GenericAgent& ped, - const LineSegment& boundary_segment) const + const LineSegment& boundarySegment) const { - const auto pt = boundary_segment.ShortestPoint(ped.pos); - const auto dist_vec = pt - ped.pos; - const auto [dist, e_iw] = dist_vec.NormAndNormalized(); + const auto closestPoint = boundarySegment.ShortestPoint(ped.pos); + const auto distanceVector = closestPoint - ped.pos; + const auto [dist, directionToBoundary] = distanceVector.NormAndNormalized(); const auto& model = std::get(ped.model); + const auto& desiredDirection = (ped.destination - ped.pos).Normalized(); + double result_e0 = desiredDirection.ScalarProduct(directionToBoundary); + double result_ei = ped.destination.ScalarProduct(directionToBoundary); + + // Check if the boundary is behind the pedestrian or the destination is behind the pedestrian + if (result_e0 < 0 && result_ei < 0) return Point(0, 0); + const auto l = model.radius; - const auto R_iw = - -model.strengthGeometryRepulsion * exp((l - dist) / model.rangeGeometryRepulsion); - return e_iw * R_iw; + const auto boundaryRepulsionStrength = + -model.strengthGeometryRepulsion * exp((l - dist) / model.rangeGeometryRepulsion); + const auto adjustedDirection = CalculateInfluenceDirection(desiredDirection, directionToBoundary); + return adjustedDirection * boundaryRepulsionStrength; + } From ec801e40142a68be96b2c78b7ac4324056adb320 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Mon, 6 Jan 2025 19:33:43 +0100 Subject: [PATCH 09/52] Update the direction according to eq 7 --- .../src/AnticipationVelocityModel.cpp | 25 +++++++++++++++++++ .../src/AnticipationVelocityModel.hpp | 2 ++ 2 files changed, 27 insertions(+) diff --git a/libsimulator/src/AnticipationVelocityModel.cpp b/libsimulator/src/AnticipationVelocityModel.cpp index 12606d014..9fc6c35f8 100644 --- a/libsimulator/src/AnticipationVelocityModel.cpp +++ b/libsimulator/src/AnticipationVelocityModel.cpp @@ -74,6 +74,8 @@ OperationalModelUpdate AnticipationVelocityModel::ComputeNewPosition( if(direction == Point{}) { direction = ped.orientation; } + // update direction towards the newly calculated direction + direction = UpdateDirection(ped, direction, dT); const auto spacing = std::accumulate( std::begin(neighborhood), std::end(neighborhood), @@ -96,6 +98,27 @@ void AnticipationVelocityModel::ApplyUpdate(const OperationalModelUpdate& upd, G agent.orientation = update.orientation; } +Point AnticipationVelocityModel::UpdateDirection(const GenericAgent& ped, const Point & calculatedDirection, double dt +) const{ + const auto& model = std::get(ped.model); + const Point desiredDirection = (ped.destination - ped.pos).Normalized(); + Point actualDirection = ped.orientation; + Point updatedDirection; + + if(desiredDirection.ScalarProduct(calculatedDirection)*desiredDirection.ScalarProduct(actualDirection) < 0) { + updatedDirection = calculatedDirection; + } + else{ + // Compute the rate of change of direction (Eq. 7) + const Point directionDerivative = + (calculatedDirection.Normalized() - actualDirection) / model.reactionTime; + updatedDirection = actualDirection + directionDerivative * dt; +} + + return updatedDirection.Normalized(); +} + + void AnticipationVelocityModel::CheckModelConstraint( const GenericAgent& agent, const NeighborhoodSearchType& neighborhoodSearch, @@ -118,6 +141,8 @@ void AnticipationVelocityModel::CheckModelConstraint( constexpr double timeGapMax = 10.; validateConstraint(timeGap, timeGapMin, timeGapMax, "timeGap"); + // TODO: Validate anticipation time and tau + const auto neighbors = neighborhoodSearch.GetNeighboringAgents(agent.pos, 2); for(const auto& neighbor : neighbors) { if(agent.id == neighbor.id) { diff --git a/libsimulator/src/AnticipationVelocityModel.hpp b/libsimulator/src/AnticipationVelocityModel.hpp index 0b6d0cf05..725ad9a68 100644 --- a/libsimulator/src/AnticipationVelocityModel.hpp +++ b/libsimulator/src/AnticipationVelocityModel.hpp @@ -40,4 +40,6 @@ class AnticipationVelocityModel : public OperationalModel GetSpacing(const GenericAgent& ped1, const GenericAgent& ped2, const Point& direction) const; Point NeighborRepulsion(const GenericAgent& ped1, const GenericAgent& ped2) const; Point BoundaryRepulsion(const GenericAgent& ped, const LineSegment& boundary_segment) const; + Point UpdateDirection(const GenericAgent& ped, const Point& calculatedDirection, double dt) const; + }; From de57a2e5c609c479aca2ce06ee36cbf07172a989 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Mon, 6 Jan 2025 19:36:23 +0100 Subject: [PATCH 10/52] validate parameters of the model --- libsimulator/src/AnticipationVelocityModel.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libsimulator/src/AnticipationVelocityModel.cpp b/libsimulator/src/AnticipationVelocityModel.cpp index 9fc6c35f8..8653279ed 100644 --- a/libsimulator/src/AnticipationVelocityModel.cpp +++ b/libsimulator/src/AnticipationVelocityModel.cpp @@ -141,7 +141,15 @@ void AnticipationVelocityModel::CheckModelConstraint( constexpr double timeGapMax = 10.; validateConstraint(timeGap, timeGapMin, timeGapMax, "timeGap"); - // TODO: Validate anticipation time and tau + const auto anticipationTime = model.anticipationTime; + constexpr double anticipationTimeMin = 0.0; + constexpr double anticipationTimeMax = 5.0; + validateConstraint(anticipationTime, anticipationTimeMin, anticipationTimeMax, "anticipationTime"); + + const auto reactionTime = model.reactionTime; + constexpr double reactionTimeMin = 0.05; + constexpr double reactionTimeMax = 1.0; + validateConstraint(reactionTime, reactionTimeMin, reactionTimeMax, "reactionTime"); const auto neighbors = neighborhoodSearch.GetNeighboringAgents(agent.pos, 2); for(const auto& neighbor : neighbors) { From 42bb1db7a66bb806f11734e50b095a9696f0042a Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 7 Jan 2025 10:37:16 +0100 Subject: [PATCH 11/52] Update functionality for walls behind walls --- .../src/AnticipationVelocityModel.cpp | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/libsimulator/src/AnticipationVelocityModel.cpp b/libsimulator/src/AnticipationVelocityModel.cpp index 8653279ed..830133a8a 100644 --- a/libsimulator/src/AnticipationVelocityModel.cpp +++ b/libsimulator/src/AnticipationVelocityModel.cpp @@ -208,15 +208,12 @@ double AnticipationVelocityModel::GetSpacing( } const auto left = direction.Rotate90Deg(); - const auto private_space = 0.5; const auto l = model1.radius + model2.radius; - - float min_dist = l + private_space;// TODO bool inCorridor = std::abs(left.ScalarProduct(distp12)) <= l; if(!inCorridor) { return std::numeric_limits::max(); } - return distp12.Norm() - min_dist; + return distp12.Norm() - l; } Point AnticipationVelocityModel::CalculateInfluenceDirection(const Point& desiredDirection, const Point& predictedDirection) const @@ -282,21 +279,38 @@ Point AnticipationVelocityModel::BoundaryRepulsion( const GenericAgent& ped, const LineSegment& boundarySegment) const { + const auto& model = std::get(ped.model); + const auto& desiredDirection = (ped.destination - ped.pos).Normalized(); + const auto closestPoint = boundarySegment.ShortestPoint(ped.pos); const auto distanceVector = closestPoint - ped.pos; const auto [dist, directionToBoundary] = distanceVector.NormAndNormalized(); - const auto& model = std::get(ped.model); - const auto& desiredDirection = (ped.destination - ped.pos).Normalized(); - double result_e0 = desiredDirection.ScalarProduct(directionToBoundary); - double result_ei = ped.destination.ScalarProduct(directionToBoundary); - // Check if the boundary is behind the pedestrian or the destination is behind the pedestrian - if (result_e0 < 0 && result_ei < 0) return Point(0, 0); + // Check if the boundary is behind the pedestrian + const std::array boundaryPoints = {boundarySegment.p1, boundarySegment.p2}; + bool boundaryBehind = true; + for (const auto& boundaryPoint : boundaryPoints) { + const auto vectorToBoundary = (boundaryPoint - ped.pos).Normalized(); + const double resultDesired = desiredDirection.ScalarProduct(vectorToBoundary); + const double resultDestination = ped.destination.ScalarProduct(vectorToBoundary); + + if (resultDesired >= 0 || resultDestination >= 0) { + boundaryBehind = false; + break; // Stop checking once a relevant point is found + } + } + if (boundaryBehind) { + return Point(0, 0); // No repulsion if the boundary is fully behind + } + // Compute the repulsion force based on distance const auto l = model.radius; const auto boundaryRepulsionStrength = - -model.strengthGeometryRepulsion * exp((l - dist) / model.rangeGeometryRepulsion); + -model.strengthGeometryRepulsion * std::exp((l - dist) / model.rangeGeometryRepulsion); + + // Adjust the influence direction const auto adjustedDirection = CalculateInfluenceDirection(desiredDirection, directionToBoundary); + return adjustedDirection * boundaryRepulsionStrength; } From 681b518306b7d66d920f0ebdfb9ffec3ce484e9a Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 7 Jan 2025 10:55:50 +0100 Subject: [PATCH 12/52] Add anticipation and reaction times to C-API --- .../jupedsim/anticipation_velocity_model.h | 38 ++++++++++++++++++- .../src/anticipation_velocity_model.cpp | 34 +++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/libjupedsim/include/jupedsim/anticipation_velocity_model.h b/libjupedsim/include/jupedsim/anticipation_velocity_model.h index 9da4714cc..17f059a8e 100644 --- a/libjupedsim/include/jupedsim/anticipation_velocity_model.h +++ b/libjupedsim/include/jupedsim/anticipation_velocity_model.h @@ -12,7 +12,7 @@ extern "C" { #endif /** - * Opaque type for a Anticipation Velocity Model Builder + * Opaque type for a Anticipation Velocity Model Builder. */ typedef struct JPS_AnticipationVelocityModelBuilder_t* JPS_AnticipationVelocityModelBuilder; @@ -27,7 +27,7 @@ JUPEDSIM_API JPS_AnticipationVelocityModelBuilder JPS_AnticipationVelocityModelB * JPS_AnticipationVelocityModelBuilder. * @param handle the builder to operate on * @param[out] errorMessage if not NULL: will be set to a JPS_ErrorMessage in case of an error - * @return a JPS_AnticipationVelocityModel or NULL if an error occured. + * @return a JPS_AnticipationVelocityModel or NULL if an error occurred. */ JUPEDSIM_API JPS_OperationalModel JPS_AnticipationVelocityModelBuilder_Build( JPS_AnticipationVelocityModelBuilder handle, @@ -79,6 +79,40 @@ JUPEDSIM_API void JPS_AnticipationVelocityModelState_SetRangeNeighborRepulsion( JPS_AnticipationVelocityModelState handle, double rangeNeighborRepulsion); +/** + * Read anticipation time of this agent. + * @param handle of the Agent to access. + * @return anticipation time of this agent + */ +JUPEDSIM_API double +JPS_AnticipationVelocityModelState_GetAnticipationTime(JPS_AnticipationVelocityModelState handle); + +/** + * Write anticipation time of this agent. + * @param handle of the Agent to access. + * @param anticipationTime of this agent. + */ +JUPEDSIM_API void JPS_AnticipationVelocityModelState_SetAnticipationTime( + JPS_AnticipationVelocityModelState handle, + double anticipationTime); + +/** + * Read reaction time of this agent. + * @param handle of the Agent to access. + * @return reaction time of this agent + */ +JUPEDSIM_API double +JPS_AnticipationVelocityModelState_GetReactionTime(JPS_AnticipationVelocityModelState handle); + +/** + * Write reaction time of this agent. + * @param handle of the Agent to access. + * @param reactionTime of this agent. + */ +JUPEDSIM_API void JPS_AnticipationVelocityModelState_SetReactionTime( + JPS_AnticipationVelocityModelState handle, + double reactionTime); + /** * Read strength geometry repulsion of this agent. * @param handle of the Agent to access. diff --git a/libjupedsim/src/anticipation_velocity_model.cpp b/libjupedsim/src/anticipation_velocity_model.cpp index e4e99c417..9860947c4 100644 --- a/libjupedsim/src/anticipation_velocity_model.cpp +++ b/libjupedsim/src/anticipation_velocity_model.cpp @@ -89,6 +89,40 @@ void JPS_AnticipationVelocityModelState_SetRangeNeighborRepulsion( state->rangeNeighborRepulsion = rangeNeighborRepulsion; } +double JPS_AnticipationVelocityModelState_GetAnticipationTime( +JPS_AnticipationVelocityModelState handle) +{ + assert(handle); + const auto state = reinterpret_cast(handle); + return state->anticipationTime; +} + +void JPS_AnticipationVelocityModelState_SetAnticipationTime( + JPS_AnticipationVelocityModelState handle, + double anticipationTime) +{ + assert(handle); + auto state = reinterpret_cast(handle); + state->anticipationTime = anticipationTime; +} + +double JPS_AnticipationVelocityModelState_GetreactionTime( +JPS_AnticipationVelocityModelState handle) +{ + assert(handle); + const auto state = reinterpret_cast(handle); + return state->reactionTime; +} + +void JPS_AnticipationVelocityModelState_SetReactionTime( + JPS_AnticipationVelocityModelState handle, + double reactionTime) +{ + assert(handle); + auto state = reinterpret_cast(handle); + state->reactionTime = reactionTime; +} + double JPS_AnticipationVelocityModelState_GetStrengthGeometryRepulsion( JPS_AnticipationVelocityModelState handle) { From 732f1a6419a5fce5fdaf9b635393ae6a74399e4d Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 7 Jan 2025 11:20:55 +0100 Subject: [PATCH 13/52] Fix bug in wall calculation --- libsimulator/src/AnticipationVelocityModel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsimulator/src/AnticipationVelocityModel.cpp b/libsimulator/src/AnticipationVelocityModel.cpp index 830133a8a..d09a93331 100644 --- a/libsimulator/src/AnticipationVelocityModel.cpp +++ b/libsimulator/src/AnticipationVelocityModel.cpp @@ -292,9 +292,9 @@ Point AnticipationVelocityModel::BoundaryRepulsion( for (const auto& boundaryPoint : boundaryPoints) { const auto vectorToBoundary = (boundaryPoint - ped.pos).Normalized(); const double resultDesired = desiredDirection.ScalarProduct(vectorToBoundary); - const double resultDestination = ped.destination.ScalarProduct(vectorToBoundary); + const double resultDirection = ped.orientation.ScalarProduct(vectorToBoundary); - if (resultDesired >= 0 || resultDestination >= 0) { + if (resultDesired >= 0 || resultDirection >= 0) { boundaryBehind = false; break; // Stop checking once a relevant point is found } From 7dfffef03837a412e0b7963ca87bfe08560bdd15 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 7 Jan 2025 11:25:08 +0100 Subject: [PATCH 14/52] rename get reaction time --- libjupedsim/src/anticipation_velocity_model.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libjupedsim/src/anticipation_velocity_model.cpp b/libjupedsim/src/anticipation_velocity_model.cpp index 9860947c4..ac161453e 100644 --- a/libjupedsim/src/anticipation_velocity_model.cpp +++ b/libjupedsim/src/anticipation_velocity_model.cpp @@ -106,7 +106,7 @@ void JPS_AnticipationVelocityModelState_SetAnticipationTime( state->anticipationTime = anticipationTime; } -double JPS_AnticipationVelocityModelState_GetreactionTime( +double JPS_AnticipationVelocityModelState_GetReactionTime( JPS_AnticipationVelocityModelState handle) { assert(handle); From 407bae0ecb1ca54961bc12d70133af67a20be568 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 7 Jan 2025 11:59:35 +0100 Subject: [PATCH 15/52] Add two parameters and remove unused parameter from AVM API --- .../jupedsim/anticipation_velocity_model.h | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/libjupedsim/include/jupedsim/anticipation_velocity_model.h b/libjupedsim/include/jupedsim/anticipation_velocity_model.h index 17f059a8e..d5b554830 100644 --- a/libjupedsim/include/jupedsim/anticipation_velocity_model.h +++ b/libjupedsim/include/jupedsim/anticipation_velocity_model.h @@ -180,22 +180,6 @@ JUPEDSIM_API void JPS_AnticipationVelocityModelState_SetTimeGap( JPS_AnticipationVelocityModelState handle, double time_gap); -/** - * Read tau of this agent. - * @param handle of the Agent to access. - * @return tau of this agent - */ -JUPEDSIM_API double -JPS_AnticipationVelocityModelState_GetTau(JPS_AnticipationVelocityModelState handle); - -/** - * Write tau of this agent. - * @param handle of the Agent to access. - * @param tau of this agent. - */ -JUPEDSIM_API void -JPS_AnticipationVelocityModelState_SetTau(JPS_AnticipationVelocityModelState handle, double tau); - /** * Read v0 of this agent. * @param handle of the Agent to access. @@ -252,11 +236,11 @@ typedef struct JPS_AnticipationVelocityModelAgentParameters { */ double time_gap = 1.; /** - *@param v0 of the agents using this profile(desired speed) double radius; + * @param v0 of the agents using this profile(desired speed) double radius; */ double v0 = 1.2; /** - *@param radius of the agent in 'meters' + * @param radius of the agent in 'meters' */ double radius = 0.2; @@ -280,6 +264,16 @@ typedef struct JPS_AnticipationVelocityModelAgentParameters { */ double rangeGeometryRepulsion{0.02}; + /** + * Anticipation time in seconds + */ + double anticipationTime{1.0}; + + /** + * Reaction time in seconds + */ + double reactionTime{0.3}; + } JPS_AnticipationVelocityModelAgentParameters; #ifdef __cplusplus From f79dd6f6ec43c9f7acf75f31da4d61f478d671cb Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 7 Jan 2025 12:00:58 +0100 Subject: [PATCH 16/52] python bindings for AVM --- .../anticipation_velocity_model.cpp | 35 ++++++++++++++++--- .../models/anticipation_velocity_model.py | 24 +++++++++++++ 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/python_bindings_jupedsim/anticipation_velocity_model.cpp b/python_bindings_jupedsim/anticipation_velocity_model.cpp index 75e7bf7af..1985e9c40 100644 --- a/python_bindings_jupedsim/anticipation_velocity_model.cpp +++ b/python_bindings_jupedsim/anticipation_velocity_model.cpp @@ -27,7 +27,9 @@ void init_anticipation_velocity_model(py::module_& m) double strengthNeighborRepulsion, double rangeNeighborRepulsion, double strengthGeometryRepulsion, - double rangeGeometryRepulsion) { + double rangeGeometryRepulsion, + double anticipationTime, + double reactionTime) { return JPS_AnticipationVelocityModelAgentParameters{ intoJPS_Point(position), journey_id, @@ -38,7 +40,9 @@ void init_anticipation_velocity_model(py::module_& m) strengthNeighborRepulsion, rangeNeighborRepulsion, strengthGeometryRepulsion, - rangeGeometryRepulsion}; + rangeGeometryRepulsion, + anticipationTime, + reactionTime}; }), py::kw_only(), py::arg("position"), @@ -50,13 +54,16 @@ void init_anticipation_velocity_model(py::module_& m) py::arg("strength_neighbor_repulsion"), py::arg("range_neighbor_repulsion"), py::arg("strength_geometry_repulsion"), - py::arg("range_geometry_repulsion")) + py::arg("range_geometry_repulsion"), + py::arg("anticipation_time"), + py::arg("reaction_time")) .def("__repr__", [](const JPS_AnticipationVelocityModelAgentParameters& p) { return fmt::format( "position: {}, journey_id: {}, stage_id: {}, " "time_gap: {}, v0: {}, radius: {}", "strength_neighbor_repulsion: {}, range_neighbor_repulsion: {}" - "strength_geometry_repulsion: {}, range_geometry_repulsion: {}", + "strength_geometry_repulsion: {}, range_geometry_repulsion: {}" + "anticipation_time: {}, reaction_time: {}", intoTuple(p.position), p.journeyId, p.stageId, @@ -66,7 +73,9 @@ void init_anticipation_velocity_model(py::module_& m) p.strengthNeighborRepulsion, p.rangeNeighborRepulsion, p.strengthGeometryRepulsion, - p.rangeGeometryRepulsion); + p.rangeGeometryRepulsion, + p.anticipationTime, + p.reactionTime); }); py::class_(m, "AnticipationVelocityModelBuilder") .def(py::init([]() { @@ -143,5 +152,21 @@ void init_anticipation_velocity_model(py::module_& m) [](JPS_AnticipationVelocityModelState_Wrapper& w, double rangeGeometryRepulsion) { JPS_AnticipationVelocityModelState_SetRangeGeometryRepulsion( w.handle, rangeGeometryRepulsion); + }) + .def_property( + "anticipation_time", + [](const JPS_AnticipationVelocityModelState_Wrapper& w) { + return JPS_AnticipationVelocityModelState_GetAnticipationTime(w.handle); + }, + [](JPS_AnticipationVelocityModelState_Wrapper& w, double anticipationTime) { + JPS_AnticipationVelocityModelState_SetAnticipationTime(w.handle, anticipationTime); + }) + .def_property( + "reaction_time", + [](const JPS_AnticipationVelocityModelState_Wrapper& w) { + return JPS_AnticipationVelocityModelState_GetReactionTime(w.handle); + }, + [](JPS_AnticipationVelocityModelState_Wrapper& w, double reactionTime) { + JPS_AnticipationVelocityModelState_SetReactionTime(w.handle, reactionTime); }); } diff --git a/python_modules/jupedsim/jupedsim/models/anticipation_velocity_model.py b/python_modules/jupedsim/jupedsim/models/anticipation_velocity_model.py index 0d4bf7a68..df91664a5 100644 --- a/python_modules/jupedsim/jupedsim/models/anticipation_velocity_model.py +++ b/python_modules/jupedsim/jupedsim/models/anticipation_velocity_model.py @@ -65,6 +65,8 @@ class AnticipationVelocityModelAgentParameters: range_neighbor_repulsion: Range of the repulsion from neighbors strength_geometry_repulsion: Strength of the repulsion from geometry boundaries range_geometry_repulsion: Range of the repulsion from geometry boundaries + anticipation_time: Anticipation time of an agent. + reaction_time: reaction time of an agent to change its direction. """ position: tuple[float, float] = (0.0, 0.0) @@ -77,6 +79,8 @@ class AnticipationVelocityModelAgentParameters: range_neighbor_repulsion: float = 0.1 strength_geometry_repulsion: float = 5.0 range_geometry_repulsion: float = 0.02 + anticipation_time: float = 1.0 + reaction_time: float = 0.3 def as_native( self, @@ -92,6 +96,8 @@ def as_native( range_neighbor_repulsion=self.range_neighbor_repulsion, strength_geometry_repulsion=self.strength_geometry_repulsion, range_geometry_repulsion=self.range_geometry_repulsion, + anticipation_time=self.anticipation_time, + reaction_time=self.reaction_time, ) @@ -160,3 +166,21 @@ def range_geometry_repulsion(self) -> float: @range_geometry_repulsion.setter def range_geometry_repulsion(self, range_geometry_repulsion): self._obj.range_geometry_repulsion = range_geometry_repulsion + + @property + def anticipation_time(self) -> float: + """Anticipation time of this agent.""" + return self._obj.anticipation_time + + @anticipation_time.setter + def anticipation_time(self, anticipation_time): + self._obj.anticipation_time = anticipation_time + + @property + def reaction_time(self) -> float: + """Reaction time of this agent.""" + return self._obj.reaction_time + + @reaction_time.setter + def reaction_time(self, reaction_time): + self._obj.reaction_time = reaction_time From efb7ca79a73b220bb0e7b5ed6903d09c02c0a5cb Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 7 Jan 2025 12:01:19 +0100 Subject: [PATCH 17/52] Add test can construct AVM --- libjupedsim/test/TestJupedsim.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libjupedsim/test/TestJupedsim.cpp b/libjupedsim/test/TestJupedsim.cpp index 81424673e..60b53cb7a 100644 --- a/libjupedsim/test/TestJupedsim.cpp +++ b/libjupedsim/test/TestJupedsim.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-or-later #include "AgentIterator.hpp" #include "Point.hpp" +#include "jupedsim/anticipation_velocity_model.h" #include "gtest/gtest.h" #include #include @@ -31,6 +32,17 @@ TEST(OperationalModel, CanConstructCollisionFreeSpeedModel) JPS_OperationalModel_Free(model); } +TEST(OperationalModel, CanConstructAnticipationVelocityModel) +{ + JPS_ErrorMessage errorMsg{}; + auto builder = JPS_AnticipationVelocityModelBuilder_Create(1, 1, 1, 1); + auto model = JPS_AnticipationVelocityModelBuilder_Build(builder, &errorMsg); + EXPECT_NE(model, nullptr); + EXPECT_EQ(errorMsg, nullptr); + JPS_AnticipationVelocityModelBuilder_Free(builder); + JPS_OperationalModel_Free(model); +} + TEST(OperationalModel, DefaultsOfCollisionFreeSpeedModelAgentParameters) { JPS_CollisionFreeSpeedModelAgentParameters agentParameters{}; From f83fbfa75d1ea4214b1d6920698c38cf69df09e5 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 7 Jan 2025 13:01:46 +0100 Subject: [PATCH 18/52] Init new parameters in libjupedsim simulation --- libjupedsim/src/simulation.cpp | 19 +++++++++++-------- .../src/AnticipationVelocityModel.cpp | 1 - python_modules/jupedsim/jupedsim/agent.py | 1 + .../models/anticipation_velocity_model.py | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/libjupedsim/src/simulation.cpp b/libjupedsim/src/simulation.cpp index f18f6352f..aeb7f0dd0 100644 --- a/libjupedsim/src/simulation.cpp +++ b/libjupedsim/src/simulation.cpp @@ -294,7 +294,7 @@ JPS_AgentId JPS_Simulation_AddAnticipationVelocityModelAgent( try { if(simulation->ModelType() != OperationalModelType::ANTICIPATION_VELOCITY_MODEL) { throw std::runtime_error( - "Simulation is not configured to use Anticipation Velocity Model"); + "Simulation is not configured to use Anticipation Velocity Model."); } GenericAgent agent( GenericAgent::ID::Invalid, @@ -303,13 +303,16 @@ JPS_AgentId JPS_Simulation_AddAnticipationVelocityModelAgent( intoPoint(parameters.position), {}, AnticipationVelocityModelData{ - parameters.strengthNeighborRepulsion, - parameters.rangeNeighborRepulsion, - parameters.strengthGeometryRepulsion, - parameters.rangeGeometryRepulsion, - parameters.time_gap, - parameters.v0, - parameters.radius}); + .strengthNeighborRepulsion = parameters.strengthNeighborRepulsion, + .rangeNeighborRepulsion = parameters.rangeNeighborRepulsion, + .strengthGeometryRepulsion = parameters.strengthGeometryRepulsion, + .rangeGeometryRepulsion = parameters.rangeGeometryRepulsion, + .anticipationTime = parameters.anticipationTime, + .reactionTime = parameters.reactionTime, + .velocity = {}, + .timeGap = parameters.time_gap, + .v0 = parameters.v0, + .radius = parameters.radius}); result = simulation->AddAgent(std::move(agent)); } catch(const std::exception& ex) { if(errorMessage) { diff --git a/libsimulator/src/AnticipationVelocityModel.cpp b/libsimulator/src/AnticipationVelocityModel.cpp index d09a93331..a2ef3f9d3 100644 --- a/libsimulator/src/AnticipationVelocityModel.cpp +++ b/libsimulator/src/AnticipationVelocityModel.cpp @@ -125,7 +125,6 @@ void AnticipationVelocityModel::CheckModelConstraint( const CollisionGeometry& geometry) const { const auto& model = std::get(agent.model); - const auto r = model.radius; constexpr double rMin = 0.; constexpr double rMax = 2.; diff --git a/python_modules/jupedsim/jupedsim/agent.py b/python_modules/jupedsim/jupedsim/agent.py index 0aacae917..d35f1ad01 100644 --- a/python_modules/jupedsim/jupedsim/agent.py +++ b/python_modules/jupedsim/jupedsim/agent.py @@ -108,6 +108,7 @@ def model( ) -> ( GeneralizedCentrifugalForceModelState | CollisionFreeSpeedModelState + | CollisionFreeSpeedModelV2State | AnticipationVelocityModelState | SocialForceModelState ): diff --git a/python_modules/jupedsim/jupedsim/models/anticipation_velocity_model.py b/python_modules/jupedsim/jupedsim/models/anticipation_velocity_model.py index df91664a5..ae9517499 100644 --- a/python_modules/jupedsim/jupedsim/models/anticipation_velocity_model.py +++ b/python_modules/jupedsim/jupedsim/models/anticipation_velocity_model.py @@ -70,7 +70,7 @@ class AnticipationVelocityModelAgentParameters: """ position: tuple[float, float] = (0.0, 0.0) - time_gap: float = 1.0 + time_gap: float = 1.06 v0: float = 1.2 radius: float = 0.2 journey_id: int = 0 From b7147a657e1e38979b30dc89d3ca05b6e0a77862 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 7 Jan 2025 13:22:27 +0100 Subject: [PATCH 19/52] Add headon examples --- examples/example8_headon_AVM.py | 65 +++++++++++++++++++++++++++++++++ examples/example8_headon_CSM.py | 61 +++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 examples/example8_headon_AVM.py create mode 100644 examples/example8_headon_CSM.py diff --git a/examples/example8_headon_AVM.py b/examples/example8_headon_AVM.py new file mode 100644 index 000000000..11750d638 --- /dev/null +++ b/examples/example8_headon_AVM.py @@ -0,0 +1,65 @@ +#! /usr/bin/env python3 + +# Copyright © 2012-2024 Forschungszentrum Jülich GmbH +# SPDX-License-Identifier: LGPL-3.0-or-later + +import pathlib +import sys + +import jupedsim as jps +import shapely +from shapely import Polygon + + +def main(): + width = 2 + length = 10 + geometry = Polygon([(0, 0), (length, 0), (length, width), (0, width)]) + num_agents = 2 + exit_polygon = Polygon( + [(length - 0.5, 0), (length, 0), (length, width), (length - 0.5, width)] + ) + trajectory_file = "headon_AVM.sqlite" + simulation = jps.Simulation( + model=jps.AnticipationVelocityModel(), + geometry=geometry, + trajectory_writer=jps.SqliteTrajectoryWriter( + output_file=pathlib.Path(trajectory_file) + ), + ) + + exit_id = simulation.add_exit_stage(exit_polygon) + journey = jps.JourneyDescription([exit_id]) + journey_id = simulation.add_journey(journey) + + start_positions = [(3, 0.5 * width), (0.5 * length, 0.5 * width)] + parameters = [ + jps.AnticipationVelocityModelAgentParameters( + journey_id=journey_id, + stage_id=exit_id, + position=start_positions[0], + radius=0.2, + v0=1.2, + ), + jps.AnticipationVelocityModelAgentParameters( + journey_id=journey_id, + stage_id=exit_id, + position=start_positions[1], + radius=0.2, + v0=0.2, + ), + ] + for position, param in zip(start_positions, parameters): + simulation.add_agent(parameters=param) + + while simulation.agent_count() > 0 and simulation.iteration_count() < 1000: + simulation.iterate() + + print( + f"Simulation completed after {simulation.iteration_count()} iterations ({simulation.elapsed_time()} s)" + ) + print(f">> {trajectory_file = }") + + +if __name__ == "__main__": + main() diff --git a/examples/example8_headon_CSM.py b/examples/example8_headon_CSM.py new file mode 100644 index 000000000..42ce6922d --- /dev/null +++ b/examples/example8_headon_CSM.py @@ -0,0 +1,61 @@ +#! /usr/bin/env python3 + +# Copyright © 2012-2024 Forschungszentrum Jülich GmbH +# SPDX-License-Identifier: LGPL-3.0-or-later + +import pathlib +import jupedsim as jps +from shapely import Polygon + + +def main(): + width = 2 + length = 10 + geometry = Polygon([(0, 0), (length, 0), (length, width), (0, width)]) + exit_polygon = Polygon( + [(length - 0.5, 0), (length, 0), (length, width), (length - 0.5, width)] + ) + trajectory_file = "headon_CSM.sqlite" + simulation = jps.Simulation( + model=jps.CollisionFreeSpeedModel(), + geometry=geometry, + trajectory_writer=jps.SqliteTrajectoryWriter( + output_file=pathlib.Path(trajectory_file) + ), + ) + + exit_id = simulation.add_exit_stage(exit_polygon) + journey = jps.JourneyDescription([exit_id]) + journey_id = simulation.add_journey(journey) + + start_positions = [(3, 0.5 * width), (0.5 * length, 0.5 * width)] + parameters = [ + jps.CollisionFreeSpeedModelAgentParameters( + journey_id=journey_id, + stage_id=exit_id, + position=start_positions[0], + radius=0.2, + v0=1.2, + ), + jps.CollisionFreeSpeedModelAgentParameters( + journey_id=journey_id, + stage_id=exit_id, + position=start_positions[1], + radius=0.2, + v0=0.2, + ), + ] + for position, param in zip(start_positions, parameters): + simulation.add_agent(parameters=param) + + while simulation.agent_count() > 0 and simulation.iteration_count() < 1000: + simulation.iterate() + + print( + f"Simulation completed after {simulation.iteration_count()} iterations ({simulation.elapsed_time()} s)" + ) + print(f">> {trajectory_file = }") + + +if __name__ == "__main__": + main() From c8df214f1ab6f95b7012f1b3966b6243bfe2f60a Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 7 Jan 2025 20:21:28 +0100 Subject: [PATCH 20/52] Wrong sign for wall influence --- libsimulator/src/AnticipationVelocityModel.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libsimulator/src/AnticipationVelocityModel.cpp b/libsimulator/src/AnticipationVelocityModel.cpp index a2ef3f9d3..cc0fa8d6b 100644 --- a/libsimulator/src/AnticipationVelocityModel.cpp +++ b/libsimulator/src/AnticipationVelocityModel.cpp @@ -305,11 +305,10 @@ Point AnticipationVelocityModel::BoundaryRepulsion( // Compute the repulsion force based on distance const auto l = model.radius; const auto boundaryRepulsionStrength = - -model.strengthGeometryRepulsion * std::exp((l - dist) / model.rangeGeometryRepulsion); + model.strengthGeometryRepulsion * std::exp((l - dist) / model.rangeGeometryRepulsion); // Adjust the influence direction const auto adjustedDirection = CalculateInfluenceDirection(desiredDirection, directionToBoundary); return adjustedDirection * boundaryRepulsionStrength; - } From df7041f7a55e5a9758c99e2948165cb4206c0a25 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Wed, 8 Jan 2025 17:36:58 +0100 Subject: [PATCH 21/52] Update velocity of agents --- libsimulator/src/AnticipationVelocityModel.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libsimulator/src/AnticipationVelocityModel.cpp b/libsimulator/src/AnticipationVelocityModel.cpp index cc0fa8d6b..ab201a482 100644 --- a/libsimulator/src/AnticipationVelocityModel.cpp +++ b/libsimulator/src/AnticipationVelocityModel.cpp @@ -94,8 +94,10 @@ void AnticipationVelocityModel::ApplyUpdate(const OperationalModelUpdate& upd, G const { const auto& update = std::get(upd); + auto& model = std::get(agent.model); agent.pos = update.position; agent.orientation = update.orientation; + model.velocity = update.velocity; } Point AnticipationVelocityModel::UpdateDirection(const GenericAgent& ped, const Point & calculatedDirection, double dt @@ -256,7 +258,7 @@ Point AnticipationVelocityModel::NeighborRepulsion( // Check perception range (Eq. 1) const auto inPerceptionRange = d1.ScalarProduct(ep12) >= 0 || e1.ScalarProduct(ep12) >= 0; if(!inPerceptionRange) return Point(0, 0); - + double S_Gap = (model1.velocity - model2.velocity).ScalarProduct(ep12) * model1.anticipationTime; double R_dist = adjustedDist - S_Gap; R_dist = std::max(R_dist, 0.0); // Clamp to zero if negative From 21bcc41f6b7bea5979e71dfff05a825122e4d317 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Thu, 9 Jan 2025 16:14:19 +0100 Subject: [PATCH 22/52] Fix bug: Apply Update velocity of agents --- libsimulator/src/AnticipationVelocityModel.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libsimulator/src/AnticipationVelocityModel.cpp b/libsimulator/src/AnticipationVelocityModel.cpp index ab201a482..b747d113d 100644 --- a/libsimulator/src/AnticipationVelocityModel.cpp +++ b/libsimulator/src/AnticipationVelocityModel.cpp @@ -87,7 +87,8 @@ OperationalModelUpdate AnticipationVelocityModel::ComputeNewPosition( const auto& model = std::get(ped.model); const auto optimal_speed = OptimalSpeed(ped, spacing, model.timeGap); const auto velocity = direction * optimal_speed; - return AnticipationVelocityModelUpdate{ped.pos + velocity * dT, direction}; + return AnticipationVelocityModelUpdate{ + .position = ped.pos + velocity * dT, .velocity = velocity, .orientation = direction}; }; void AnticipationVelocityModel::ApplyUpdate(const OperationalModelUpdate& upd, GenericAgent& agent) @@ -190,7 +191,7 @@ double AnticipationVelocityModel::OptimalSpeed( double time_gap) const { const auto& model = std::get(ped.model); - double min_spacing = -0.1; + double min_spacing = 0.0; return std::min(std::max(spacing / time_gap, min_spacing ), model.v0); } From 23305ae21fe994b707d5ba9b134c58c0e5f16d79 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Thu, 9 Jan 2025 20:17:32 +0100 Subject: [PATCH 23/52] Fix missmatch of neighbor and geometry parameters --- libjupedsim/src/anticipation_velocity_model.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libjupedsim/src/anticipation_velocity_model.cpp b/libjupedsim/src/anticipation_velocity_model.cpp index ac161453e..d58cd99fc 100644 --- a/libjupedsim/src/anticipation_velocity_model.cpp +++ b/libjupedsim/src/anticipation_velocity_model.cpp @@ -145,16 +145,16 @@ double JPS_AnticipationVelocityModelState_GetRangeGeometryRepulsion( { assert(handle); const auto state = reinterpret_cast(handle); - return state->rangeNeighborRepulsion; + return state->rangeGeometryRepulsion; } void JPS_AnticipationVelocityModelState_SetRangeGeometryRepulsion( JPS_AnticipationVelocityModelState handle, - double rangeNeighborRepulsion) + double rangeGeometryRepulsion) { assert(handle); auto state = reinterpret_cast(handle); - state->rangeNeighborRepulsion = rangeNeighborRepulsion; + state->rangeGeometryRepulsion = rangeGeometryRepulsion; } double JPS_AnticipationVelocityModelState_GetTimeGap(JPS_AnticipationVelocityModelState handle) From f8a5ca16bd220386196cef706a39146d8f19fcd4 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Fri, 10 Jan 2025 15:59:13 +0100 Subject: [PATCH 24/52] Implement sliding walls The original paper doesn't include a model of how walls affect things. Usually, a valid simulation is a balance between the repulsion of the nearest point on a wall and that of the neighbour. The distance to the wall isn't considered when the speed is calculated, so a pedestrian might be 'pushed' towards a wall and so leave the walkable area. This implementation removes all these imbalances as follows: First, we calculate the combined direction from the desired direction and the neighbour's influence. Next, we determine the nearest wall to the agent. If the agent is within a critical distance of the wall and their direction has a component pointing towards it, we project their direction to be parallel to the wall. This makes walls act as "sliding surfaces" when agents get too close. The two parameters of the wall repulsion will be removed. To do this, we will have to add a new parameter called wall_buffer_distance, which determines how close an agent can come to a wall before "sliding". --- .../src/AnticipationVelocityModel.cpp | 54 +++++++++++++------ 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/libsimulator/src/AnticipationVelocityModel.cpp b/libsimulator/src/AnticipationVelocityModel.cpp index b747d113d..6e1f85b35 100644 --- a/libsimulator/src/AnticipationVelocityModel.cpp +++ b/libsimulator/src/AnticipationVelocityModel.cpp @@ -61,19 +61,44 @@ OperationalModelUpdate AnticipationVelocityModel::ComputeNewPosition( return res + NeighborRepulsion(ped, neighbor); }); - const auto boundaryRepulsion = std::accumulate( - boundary.cbegin(), - boundary.cend(), - Point(0, 0), - [this, &ped](const auto& acc, const auto& element) { - return acc + BoundaryRepulsion(ped, element); - }); - - const auto desired_direction = (ped.destination - ped.pos).Normalized(); - auto direction = (desired_direction + neighborRepulsion + boundaryRepulsion).Normalized(); + const auto desiredDirection = (ped.destination - ped.pos).Normalized(); + auto direction = (desiredDirection + neighborRepulsion).Normalized(); if(direction == Point{}) { direction = ped.orientation; } + + // Wall sliding behavior + const auto& model = std::get(ped.model); + const double wallBufferDistance = 0.2; + const double criticalWallDistance = wallBufferDistance + model.radius; // TODO: Model parameter for boundary effects: wall_buffer_distance + auto nearestWallIt = std::min_element( + boundary.cbegin(), + boundary.cend(), + [&ped](const auto& wall1, const auto& wall2) { + const auto distanceVector1 = ped.pos - wall1.ShortestPoint(ped.pos); + const auto distanceVector2 = ped.pos - wall2.ShortestPoint(ped.pos); + return distanceVector1.Norm() < distanceVector2.Norm(); + }); + if(nearestWallIt != boundary.end()) { + const auto closestPoint = nearestWallIt->ShortestPoint(ped.pos); + const auto distanceVector = ped.pos - closestPoint; + auto [perpendicularDistance, directionAwayFromBoundary] = distanceVector.NormAndNormalized(); + + if(perpendicularDistance < criticalWallDistance) { + // Agent is too close to wall + const auto dotProduct = direction.ScalarProduct(directionAwayFromBoundary); + if(dotProduct < 0) { + // ... and it is moving towards it + // Get wall direction (parallel to wall) + const auto wallVector = nearestWallIt->p2 - nearestWallIt->p1; + const auto wallDirection = wallVector.Normalized(); + + // Project direction onto wall + const auto parallelComponent = wallDirection * direction.ScalarProduct(wallDirection); + direction = parallelComponent.Normalized(); + } + } + } // update direction towards the newly calculated direction direction = UpdateDirection(ped, direction, dT); const auto spacing = std::accumulate( @@ -84,7 +109,6 @@ OperationalModelUpdate AnticipationVelocityModel::ComputeNewPosition( return std::min(res, GetSpacing(ped, neighbor, direction)); }); - const auto& model = std::get(ped.model); const auto optimal_speed = OptimalSpeed(ped, spacing, model.timeGap); const auto velocity = direction * optimal_speed; return AnticipationVelocityModelUpdate{ @@ -149,7 +173,7 @@ void AnticipationVelocityModel::CheckModelConstraint( validateConstraint(anticipationTime, anticipationTimeMin, anticipationTimeMax, "anticipationTime"); const auto reactionTime = model.reactionTime; - constexpr double reactionTimeMin = 0.05; + constexpr double reactionTimeMin = 0.01; constexpr double reactionTimeMax = 1.0; validateConstraint(reactionTime, reactionTimeMin, reactionTimeMax, "reactionTime"); @@ -221,9 +245,7 @@ double AnticipationVelocityModel::GetSpacing( Point AnticipationVelocityModel::CalculateInfluenceDirection(const Point& desiredDirection, const Point& predictedDirection) const { // Eq. (5) - const double seed = 42; - static std::random_device rd; - static std::mt19937 gen(seed); + static std::mt19937 gen(42); static std::uniform_int_distribution dist(0, 1); // Random integers: 0 or 1 Point orthogonalDirection = Point(-desiredDirection.y, desiredDirection.x).Normalized(); @@ -231,7 +253,7 @@ Point AnticipationVelocityModel::CalculateInfluenceDirection(const Point& desire Point influenceDirection = orthogonalDirection; if (fabs(alignment) < J_EPS) { // Choose a random direction (left or right) - if (dist(gen) % 2 == 0) { + if (dist(gen) == 0) { influenceDirection = -orthogonalDirection; } } else if (alignment > 0) { From 269b60871b950e214ee0c518fe43ae3e7c293408 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 14 Jan 2025 17:21:45 +0100 Subject: [PATCH 25/52] Refactor sliding walls --- .../src/AnticipationVelocityModel.cpp | 106 +++++++----------- .../src/AnticipationVelocityModel.hpp | 9 +- 2 files changed, 51 insertions(+), 64 deletions(-) diff --git a/libsimulator/src/AnticipationVelocityModel.cpp b/libsimulator/src/AnticipationVelocityModel.cpp index 6e1f85b35..392fdf53d 100644 --- a/libsimulator/src/AnticipationVelocityModel.cpp +++ b/libsimulator/src/AnticipationVelocityModel.cpp @@ -67,38 +67,16 @@ OperationalModelUpdate AnticipationVelocityModel::ComputeNewPosition( direction = ped.orientation; } - // Wall sliding behavior const auto& model = std::get(ped.model); - const double wallBufferDistance = 0.2; - const double criticalWallDistance = wallBufferDistance + model.radius; // TODO: Model parameter for boundary effects: wall_buffer_distance - auto nearestWallIt = std::min_element( - boundary.cbegin(), - boundary.cend(), - [&ped](const auto& wall1, const auto& wall2) { - const auto distanceVector1 = ped.pos - wall1.ShortestPoint(ped.pos); - const auto distanceVector2 = ped.pos - wall2.ShortestPoint(ped.pos); - return distanceVector1.Norm() < distanceVector2.Norm(); - }); - if(nearestWallIt != boundary.end()) { - const auto closestPoint = nearestWallIt->ShortestPoint(ped.pos); - const auto distanceVector = ped.pos - closestPoint; - auto [perpendicularDistance, directionAwayFromBoundary] = distanceVector.NormAndNormalized(); - - if(perpendicularDistance < criticalWallDistance) { - // Agent is too close to wall - const auto dotProduct = direction.ScalarProduct(directionAwayFromBoundary); - if(dotProduct < 0) { - // ... and it is moving towards it - // Get wall direction (parallel to wall) - const auto wallVector = nearestWallIt->p2 - nearestWallIt->p1; - const auto wallDirection = wallVector.Normalized(); + const double wallBufferDistance = 0.1; // TODO model parameter + // Wall sliding behavior + direction = HandleWallAvoidance( + direction, + ped.pos, + model.radius, + boundary, + wallBufferDistance); - // Project direction onto wall - const auto parallelComponent = wallDirection * direction.ScalarProduct(wallDirection); - direction = parallelComponent.Normalized(); - } - } - } // update direction towards the newly calculated direction direction = UpdateDirection(ped, direction, dT); const auto spacing = std::accumulate( @@ -299,41 +277,43 @@ Point AnticipationVelocityModel::NeighborRepulsion( } -Point AnticipationVelocityModel::BoundaryRepulsion( - const GenericAgent& ped, - const LineSegment& boundarySegment) const + +Point AnticipationVelocityModel::HandleWallAvoidance( + const Point& direction, + const Point& agentPosition, + double agentRadius, + const std::vector& boundary, + double wallBufferDistance) const { - const auto& model = std::get(ped.model); - const auto& desiredDirection = (ped.destination - ped.pos).Normalized(); - - const auto closestPoint = boundarySegment.ShortestPoint(ped.pos); - const auto distanceVector = closestPoint - ped.pos; - const auto [dist, directionToBoundary] = distanceVector.NormAndNormalized(); - - // Check if the boundary is behind the pedestrian - const std::array boundaryPoints = {boundarySegment.p1, boundarySegment.p2}; - bool boundaryBehind = true; - for (const auto& boundaryPoint : boundaryPoints) { - const auto vectorToBoundary = (boundaryPoint - ped.pos).Normalized(); - const double resultDesired = desiredDirection.ScalarProduct(vectorToBoundary); - const double resultDirection = ped.orientation.ScalarProduct(vectorToBoundary); - - if (resultDesired >= 0 || resultDirection >= 0) { - boundaryBehind = false; - break; // Stop checking once a relevant point is found - } - } - if (boundaryBehind) { - return Point(0, 0); // No repulsion if the boundary is fully behind - } + const double criticalWallDistance = wallBufferDistance + agentRadius; - // Compute the repulsion force based on distance - const auto l = model.radius; - const auto boundaryRepulsionStrength = - model.strengthGeometryRepulsion * std::exp((l - dist) / model.rangeGeometryRepulsion); + auto nearestWallIt = std::min_element( + boundary.cbegin(), + boundary.cend(), + [&agentPosition](const auto& wall1, const auto& wall2) { + const auto distanceVector1 = agentPosition - wall1.ShortestPoint(agentPosition); + const auto distanceVector2 = agentPosition - wall2.ShortestPoint(agentPosition); + return distanceVector1.Norm() < distanceVector2.Norm(); + }); - // Adjust the influence direction - const auto adjustedDirection = CalculateInfluenceDirection(desiredDirection, directionToBoundary); + if(nearestWallIt != boundary.end()) { + const auto closestPoint = nearestWallIt->ShortestPoint(agentPosition); + const auto distanceVector = agentPosition - closestPoint; + auto [perpendicularDistance, directionAwayFromBoundary] = distanceVector.NormAndNormalized(); + + if(perpendicularDistance < criticalWallDistance) { + // Agent is too close to wall + const auto dotProduct = direction.ScalarProduct(directionAwayFromBoundary); + if(dotProduct < 0) { + // Agent is moving towards wall + const auto wallVector = nearestWallIt->p2 - nearestWallIt->p1; + const auto wallDirection = wallVector.Normalized(); + // Project direction onto wall + const auto parallelComponent = wallDirection * direction.ScalarProduct(wallDirection); + return parallelComponent.Normalized(); + } + } + } - return adjustedDirection * boundaryRepulsionStrength; + return direction; // Return original direction if no wall correction needed } diff --git a/libsimulator/src/AnticipationVelocityModel.hpp b/libsimulator/src/AnticipationVelocityModel.hpp index 725ad9a68..5a02ae149 100644 --- a/libsimulator/src/AnticipationVelocityModel.hpp +++ b/libsimulator/src/AnticipationVelocityModel.hpp @@ -39,7 +39,14 @@ class AnticipationVelocityModel : public OperationalModel double GetSpacing(const GenericAgent& ped1, const GenericAgent& ped2, const Point& direction) const; Point NeighborRepulsion(const GenericAgent& ped1, const GenericAgent& ped2) const; - Point BoundaryRepulsion(const GenericAgent& ped, const LineSegment& boundary_segment) const; + + Point HandleWallAvoidance( + const Point& direction, + const Point& agentPosition, + double agentRadius, + const std::vector& boundary, + double wallBufferDistance) const; + Point UpdateDirection(const GenericAgent& ped, const Point& calculatedDirection, double dt) const; }; From bdd9299a7ae34bdcc3dc012062aa2ed2803ce6cf Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 14 Jan 2025 17:24:37 +0100 Subject: [PATCH 26/52] Add notebook to compare all models --- notebooks/model_comparison.ipynb | 1114 ++++++++++++++++++++++++++++++ 1 file changed, 1114 insertions(+) create mode 100644 notebooks/model_comparison.ipynb diff --git a/notebooks/model_comparison.ipynb b/notebooks/model_comparison.ipynb new file mode 100644 index 000000000..fd9d10d22 --- /dev/null +++ b/notebooks/model_comparison.ipynb @@ -0,0 +1,1114 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4b5a43f7-9248-4302-ba6e-9eb86c490be2", + "metadata": {}, + "source": [ + "# Comparative Analysis of Pedestrian Dynamics Models\n", + "\n", + "## Objective\n", + "\n", + "This notebook compares four pedestrian dynamics models by simulating agent behavior in a structured environment. Using simplified scenarios, we analyze how each model handles navigation, obstacle avoidance, and agent interactions. This comparison reveals the strengths and weaknesses of each approach, helping inform model selection when using JuPedSim.\n", + "\n", + "> **Note:** \n", + "> All models are utilized with their default parameter settings as defined in **JuPedSim**.\n", + "\n", + "## Models Under Investigation\n", + "\n", + "1. [**Collision-Free Speed Model (CSM):**](https://pedestriandynamics.org/models/collision_free_speed_model/) \n", + " A velocity-based model focused on ensuring agents move without collisions by dynamically adjusting their speeds.\n", + "\n", + "2. [**Anticipation Velocity Model (AVM):**](https://doi.org/10.1016/j.trc.2021.103464) \n", + " A model that incorporates anticipation and reaction times, allowing agents to predict and avoid potential collisions.\n", + "\n", + "3. [**Social Force Model (SFM):**](https://pedestriandynamics.org/models/social_force_model/)\n", + " A force-based model where agents are influenced by attractive forces toward goals and repulsive forces from obstacles and other agents.\n", + "\n", + "4. [**Generalized Centrifugal Force Model (GCFM):**](https://pedestriandynamics.org/models/generalized_centrifugal_force_model/) \n", + " An enhanced force-based model where agents experience centrifugal forces to better simulate realistic avoidance behavior.\n", + "\n", + "## Simulation Workflow\n", + "\n", + "- **Environment Setup:**\n", + " Defining the simulation environment with walls and obstacles to challenge agent navigation.\n", + "\n", + "- **Agent Initialization:** \n", + " Assigning starting positions, desired speeds, and target goals for agents.\n", + "\n", + "- **Model Execution:** \n", + " Running the simulation for each model and recording agent trajectories.\n", + "\n", + "- **Visualization:** \n", + " Animating and displaying the results of all models side by side to enable direct comparison of their behaviors.\n", + "\n", + " Moreover. evacuation times for all runs are ploted per model.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d47dee54-2a46-4c65-89b0-f70fe743ecfe", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "import pathlib\n", + "import jupedsim as jps\n", + "import matplotlib.pyplot as plt\n", + "import pedpy\n", + "import shapely\n", + "from matplotlib.patches import Circle\n", + "from shapely import Polygon\n", + "from jupedsim.internal.notebook_utils import animate, read_sqlite_file\n", + "from shapely.ops import unary_union\n", + "import ipywidgets as widgets\n", + "import pedpy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b982aeaf-a056-4870-bf96-4213db17ddcd", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "def initialize_simulation(\n", + " model, agent_parameters, geometry, goals, positions, speeds, trajectory_file\n", + "):\n", + " simulation = jps.Simulation(\n", + " model=model,\n", + " geometry=geometry,\n", + " dt=0.01,\n", + " trajectory_writer=jps.SqliteTrajectoryWriter(\n", + " output_file=pathlib.Path(trajectory_file), every_nth_frame=5\n", + " ),\n", + " )\n", + "\n", + " exit_ids = [simulation.add_exit_stage(goal) for goal in goals]\n", + " journey = jps.JourneyDescription(exit_ids)\n", + " journey_id = simulation.add_journey(journey)\n", + " for pos, v0, exit_id in zip(positions, speeds, exit_ids):\n", + " if agent_parameters == jps.AnticipationVelocityModelAgentParameters:\n", + " simulation.add_agent(\n", + " agent_parameters(\n", + " journey_id=journey_id,\n", + " stage_id=exit_id,\n", + " v0=v0,\n", + " position=pos,\n", + " anticipation_time=1,\n", + " reaction_time=0.3,\n", + " )\n", + " )\n", + " elif agent_parameters == jps.SocialForceModelAgentParameters:\n", + " simulation.add_agent(\n", + " agent_parameters(\n", + " journey_id=journey_id,\n", + " stage_id=exit_id,\n", + " desiredSpeed=v0,\n", + " position=pos,\n", + " )\n", + " )\n", + " else:\n", + " simulation.add_agent(\n", + " agent_parameters(\n", + " journey_id=journey_id,\n", + " stage_id=exit_id,\n", + " position=pos,\n", + " v0=v0,\n", + " )\n", + " )\n", + "\n", + " return simulation\n", + "\n", + "\n", + "def plot_simulation_configuration(geometry, starting_positions, exit_areas):\n", + " \"\"\"Plot setup for visual inspection.\"\"\"\n", + " walkable_area = pedpy.WalkableArea(geometry)\n", + " axes = pedpy.plot_walkable_area(walkable_area=walkable_area)\n", + " for exit_area in exit_areas:\n", + " axes.fill(*exit_area.exterior.xy, color=\"indianred\")\n", + " \n", + " axes.scatter(*zip(*starting_positions), label=\"Starting Position\")\n", + " axes.set_xlabel(\"x/m\")\n", + " axes.set_ylabel(\"y/m\")\n", + " axes.set_aspect(\"equal\")\n", + " axes.grid(True, alpha=0.3)\n", + "\n", + "def plot_evacuation_times(times_dict, figsize=(10, 6)):\n", + " \"\"\"\n", + " Plot evacuation times for different pedestrian models.\n", + " \"\"\"\n", + " fig = plt.figure(figsize=figsize)\n", + " \n", + " # Create bar chart\n", + " bars = plt.bar(list(times_dict.keys()), list(times_dict.values()))\n", + " \n", + " # Customize the plot\n", + " plt.title('Evacuation Times by Model')\n", + " plt.ylabel('Time (seconds)')\n", + " plt.grid(axis='y', linestyle='--', alpha=0.7)\n", + " \n", + " # Add value labels on top of each bar\n", + " for bar in bars:\n", + " height = bar.get_height()\n", + " plt.text(bar.get_x() + bar.get_width()/2., height,\n", + " f'{height:.1f}s',\n", + " ha='center', va='bottom')\n", + " \n", + " plt.tight_layout()\n", + " return fig\n", + "\n", + "\n", + "def run_simulation(simulation, max_iterations=4000):\n", + " while (\n", + " simulation.agent_count() > 0 and simulation.iteration_count() < max_iterations\n", + " ):\n", + " simulation.iterate()\n", + " print(f\"Evacuation time: {simulation.elapsed_time():.2f} s\")\n", + " return simulation.elapsed_time()" + ] + }, + { + "cell_type": "markdown", + "id": "625d2d09-f624-4d7a-b82f-0897cbf8bc35", + "metadata": {}, + "source": [ + "## Scenario 1: Crossing Paths in Rooms\n", + "\n", + "Four agents navigate between interconnected rooms with obstacles. Each agent aims to reach the diagonally opposite goal. Agents are expected to plan paths around obstacles while interacting with other agents in the corridors.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ad9ec391-b8c6-4dc4-9255-51d0d8d7e194", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "def create_geometry_scenario1():\n", + " outer_boundary = Polygon([(0, 0), (10, 0), (10, 10), (0, 10)])\n", + " walls = [\n", + " Polygon([(4.9, 0), (5.1, 0), (5.1, 3.8), (4.9, 3.8)]),\n", + " Polygon([(4.9, 6.2), (5.1, 6.2), (5.1, 10), (4.9, 10)]),\n", + " Polygon([(0, 4.9), (3.8, 4.9), (3.8, 5.1), (0, 5.1)]),\n", + " Polygon([(6.2, 4.9), (10, 4.9), (10, 5.1), (6.2, 5.1)]),\n", + " Polygon([(2.0, 2.0), (3.0, 2.0), (3.0, 3.0), (2.0, 3.0)]),\n", + " Polygon([(7.0, 2.0), (8.0, 2.0), (8.0, 3.0), (7.0, 3.0)]),\n", + " Polygon([(2.0, 7.0), (3.0, 7.0), (3.0, 6.0), (2.0, 6.0)]),\n", + " Polygon([(7.0, 7.0), (8.0, 7.0), (8.0, 6.0), (7.0, 6.0)]),\n", + " ]\n", + "\n", + " geometry = outer_boundary.difference(unary_union(walls))\n", + " return geometry\n", + "\n", + "\n", + "def define_positions_scenario1():\n", + " \"\"\"Define initial positions and desired speeds.\"\"\"\n", + " positions = [(1, 1), (9, 9), (1, 9), (9, 1)]\n", + " speeds = [1.0, 1.0, 1.0, 1.0]\n", + " return positions, speeds\n", + "\n", + "\n", + "def define_goals_scenario1():\n", + " \"\"\"Define goal polygons.\"\"\"\n", + " goals = [\n", + " Polygon([(8.5, 8.5), (9.5, 8.5), (9.5, 9.5), (8.5, 9.5)]),\n", + " Polygon([(0.5, 0.5), (1.5, 0.5), (1.5, 1.5), (0.5, 1.5)]),\n", + " Polygon([(8.5, 0.5), (9.5, 0.5), (9.5, 1.5), (8.5, 1.5)]),\n", + " Polygon([(0.5, 8.5), (1.5, 8.5), (1.5, 9.5), (0.5, 9.5)]),\n", + " ]\n", + " return goals\n", + "\n", + "geometry = create_geometry_scenario1()\n", + "goals = define_goals_scenario1()\n", + "positions, speeds = define_positions_scenario1()\n", + "plot_simulation_configuration(geometry, positions, goals)\n", + "times_dict = {}" + ] + }, + { + "cell_type": "markdown", + "id": "6afbde36-10eb-4852-87b2-f181e2e6af5e", + "metadata": {}, + "source": [ + "### CSM Simulation\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dc5ef18b-4c28-43ae-a764-5fb067d486d1", + "metadata": {}, + "outputs": [], + "source": [ + "model = \"CFM\"\n", + "trajectory_file = f\"{model}.sqlite\"\n", + "simulation = initialize_simulation(\n", + " jps.CollisionFreeSpeedModelV2(),\n", + " jps.CollisionFreeSpeedModelV2AgentParameters,\n", + " geometry,\n", + " goals,\n", + " positions,\n", + " speeds,\n", + " trajectory_file,\n", + ")\n", + "times_dict[model] = run_simulation(simulation, max_iterations=5000)\n", + "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", + "fig1 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + ] + }, + { + "cell_type": "markdown", + "id": "3a94b4b1-c4ec-40d9-bb04-6c47559d3ff5", + "metadata": {}, + "source": [ + "### AVM Simulation\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c9221227-10c5-4869-8591-7f83b16c2c46", + "metadata": {}, + "outputs": [], + "source": [ + "model = \"AVM\"\n", + "trajectory_file = f\"{model}.sqlite\"\n", + "simulation = initialize_simulation(\n", + " jps.AnticipationVelocityModel(),\n", + " jps.AnticipationVelocityModelAgentParameters,\n", + " geometry,\n", + " goals,\n", + " positions,\n", + " speeds,\n", + " trajectory_file,\n", + ")\n", + "times_dict[model] = run_simulation(simulation, max_iterations=5000)\n", + "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", + "fig2 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + ] + }, + { + "cell_type": "markdown", + "id": "ca674e50-ff18-49ff-942e-6afd9902622f", + "metadata": {}, + "source": [ + "### SFM Simulation\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d553fe0b-5f46-408b-93c2-1354be3c2d7a", + "metadata": {}, + "outputs": [], + "source": [ + "model = \"SFM\"\n", + "trajectory_file = f\"{model}.sqlite\"\n", + "simulation = initialize_simulation(\n", + " jps.SocialForceModel(),\n", + " jps.SocialForceModelAgentParameters,\n", + " geometry,\n", + " goals,\n", + " positions,\n", + " speeds,\n", + " trajectory_file,\n", + ")\n", + "times_dict[model] = run_simulation(simulation, max_iterations=5000)\n", + "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", + "fig3 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + ] + }, + { + "cell_type": "markdown", + "id": "5ec92ce4-914d-4a08-a1e8-a12c6266f9c6", + "metadata": {}, + "source": [ + "### GCFM Simulation\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f9850b99-1805-4a2e-af9e-1fa76a20dfc3", + "metadata": {}, + "outputs": [], + "source": [ + "model = \"GCFM\"\n", + "trajectory_file = f\"{model}.sqlite\"\n", + "simulation = initialize_simulation(\n", + " jps.GeneralizedCentrifugalForceModel(),\n", + " jps.GeneralizedCentrifugalForceModelAgentParameters,\n", + " geometry,\n", + " goals,\n", + " positions,\n", + " speeds,\n", + " trajectory_file,\n", + ")\n", + "times_dict[model] = run_simulation(simulation, max_iterations=5000)\n", + "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", + "fig4 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + ] + }, + { + "cell_type": "markdown", + "id": "884203af-0af3-474e-a4a9-646ab3988478", + "metadata": {}, + "source": [ + "### Visualization\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8ff1110a-b542-4966-93b7-a494a7b5a767", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "widgets_list = [widgets.Output() for _ in range(4)]\n", + "figs = [fig1, fig2, fig3, fig4]\n", + "\n", + "# Display figures in widgets\n", + "for widget, fig in zip(widgets_list, figs):\n", + " with widget:\n", + " fig.show()\n", + "\n", + "# Arrange in two rows\n", + "row1 = widgets.HBox([widgets_list[0], widgets_list[1]])\n", + "row2 = widgets.HBox([widgets_list[2], widgets_list[3]])\n", + "\n", + "# Display the 4 animations\n", + "widgets.VBox([row1, row2])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "38454c9e-32b2-4521-9a54-5d608b7345ca", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "fig = plot_evacuation_times(times_dict)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "790f4f70-432b-4bcd-a467-5df58259e054", + "metadata": {}, + "source": [ + "## Scenario 2: Following Behavior\n", + "\n", + "A single-line setup where one agent follows another slower-moving agent, testing how the models handle speed adjustments and eventually overtaking.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "20c9eb29-34d3-46fc-a206-2273934b290c", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "def create_geometry_scenario2():\n", + " geometry = Polygon([(-3, -2), (16, -2), (16, 2), (-3, 2)])\n", + " return geometry\n", + "\n", + "\n", + "def define_positions_scenario2():\n", + " \"\"\"Define initial positions and desired speeds.\"\"\"\n", + " positions = [\n", + " (-2, 0),\n", + " (2, 0),\n", + " ]\n", + " speeds = [\n", + " 1.0,\n", + " 0.5,\n", + " ]\n", + " return positions, speeds\n", + "\n", + "\n", + "def define_goals_scenario2():\n", + " \"\"\"Define goal polygons.\"\"\"\n", + " goals = [\n", + " Polygon([(12, -1), (15, -1), (15, 1), (12, 1)]),\n", + " Polygon([(12, -1), (15, -1), (15, 1), (12, 1)]),\n", + " ]\n", + " return goals\n", + "\n", + "geometry = create_geometry_scenario2()\n", + "positions, speeds = define_positions_scenario2()\n", + "goals = define_goals_scenario2()\n", + "plot_simulation_configuration(geometry, positions, goals)\n", + "times_dict = {}" + ] + }, + { + "cell_type": "markdown", + "id": "1dc114b6-0b4f-422d-940a-8c75776f687d", + "metadata": {}, + "source": [ + "### CSM Simulation\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7225ac10-e170-4733-b0ca-507516f87259", + "metadata": {}, + "outputs": [], + "source": [ + "model = \"CFM\"\n", + "trajectory_file = f\"{model}.sqlite\"\n", + "simulation = initialize_simulation(\n", + " jps.CollisionFreeSpeedModelV2(),\n", + " jps.CollisionFreeSpeedModelV2AgentParameters,\n", + " geometry,\n", + " goals,\n", + " positions,\n", + " speeds,\n", + " trajectory_file,\n", + ")\n", + "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", + "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", + "fig1 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + ] + }, + { + "cell_type": "markdown", + "id": "0a65cae5-f2f3-4c29-b357-a6f2b1f28d1a", + "metadata": {}, + "source": [ + "### AVM Simulation\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "047b1727-210a-4fb5-bdd1-e7432f255193", + "metadata": {}, + "outputs": [], + "source": [ + "model = \"AVM\"\n", + "trajectory_file = f\"{model}.sqlite\"\n", + "simulation = initialize_simulation(\n", + " jps.AnticipationVelocityModel(),\n", + " jps.AnticipationVelocityModelAgentParameters,\n", + " geometry,\n", + " goals,\n", + " positions,\n", + " speeds,\n", + " trajectory_file,\n", + ")\n", + "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", + "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", + "fig2 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + ] + }, + { + "cell_type": "markdown", + "id": "4b02fbfa-251a-43d9-97ed-ca6e5f6784ff", + "metadata": {}, + "source": [ + "### SFM Simulation\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "14cedaae-4b5f-4b0a-8667-a7d350e3a4d8", + "metadata": {}, + "outputs": [], + "source": [ + "model = \"SFM\"\n", + "trajectory_file = f\"{model}.sqlite\"\n", + "simulation = initialize_simulation(\n", + " jps.SocialForceModel(),\n", + " jps.SocialForceModelAgentParameters,\n", + " geometry,\n", + " goals,\n", + " positions,\n", + " speeds,\n", + " trajectory_file,\n", + ")\n", + "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", + "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", + "fig3 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + ] + }, + { + "cell_type": "markdown", + "id": "de75158d-3073-4ef7-a17c-9d1b94f16fbc", + "metadata": {}, + "source": [ + "### GCFM Simulation\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cd4b3e6f-0c34-4e18-8b62-4e9bb2464e97", + "metadata": {}, + "outputs": [], + "source": [ + "model = \"GCFM\"\n", + "trajectory_file = f\"{model}.sqlite\"\n", + "simulation = initialize_simulation(\n", + " jps.GeneralizedCentrifugalForceModel(),\n", + " jps.GeneralizedCentrifugalForceModelAgentParameters,\n", + " geometry,\n", + " goals,\n", + " positions,\n", + " speeds,\n", + " trajectory_file,\n", + ")\n", + "times_dict[model] = run_simulation(simulation, max_iterations=5000)\n", + "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", + "fig4 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + ] + }, + { + "cell_type": "markdown", + "id": "4da400b6-72c2-4034-a10b-a4370eda8232", + "metadata": {}, + "source": [ + "### Visualization\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9a094237-a8b2-49ae-96a9-013f4fe397eb", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "widgets_list = [widgets.Output() for _ in range(4)]\n", + "figs = [fig1, fig2, fig3, fig4]\n", + "\n", + "# Display figures in widgets\n", + "for widget, fig in zip(widgets_list, figs):\n", + " with widget:\n", + " fig.show()\n", + "\n", + "# Arrange in two rows\n", + "row1 = widgets.HBox([widgets_list[0], widgets_list[1]])\n", + "row2 = widgets.HBox([widgets_list[2], widgets_list[3]])\n", + "\n", + "# Display the 4 animations\n", + "widgets.VBox([row1, row2])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a4f33439-71a1-450a-aee2-ab102db7c787", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "fig = plot_evacuation_times(times_dict)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "6f9f6b1f", + "metadata": {}, + "source": [ + "## Scenario 3: Head-on Encounter\n", + "\n", + "Two agents approach each other on a straight line, evaluating how different models resolve direct confrontation and determine which agent yields or how they negotiate passing space.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8894d9c1", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "def create_geometry_scenario3():\n", + " geometry = Polygon([(-10, -2), (10, -2), (10, 2), (-10, 2)])\n", + " return geometry\n", + "\n", + "\n", + "def define_positions_scenario3():\n", + " \"\"\"Define initial positions and desired speeds.\"\"\"\n", + " positions = [\n", + " (-2, 0),\n", + " (2, 0),\n", + " ]\n", + " speeds = [\n", + " 1.0,\n", + " 1.0,\n", + " ]\n", + " return positions, speeds\n", + "\n", + "\n", + "def define_goals_scenario3():\n", + " \"\"\"Define goal polygons.\"\"\"\n", + " goals = [\n", + " Polygon([(6, -1), (9, -1), (9, 1), (6, 1)]),\n", + " Polygon([(-9, -1), (-6, -1), (-6, 1), (-9, 1)]),\n", + " ]\n", + " return goals\n", + "\n", + "geometry = create_geometry_scenario3()\n", + "positions, speeds = define_positions_scenario3()\n", + "goals = define_goals_scenario3()\n", + "plot_simulation_configuration(geometry, positions, goals)\n", + "times_dict = {}" + ] + }, + { + "cell_type": "markdown", + "id": "5deb294f", + "metadata": {}, + "source": [ + "### CSM Simulation\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "acdfbfcd", + "metadata": {}, + "outputs": [], + "source": [ + "model = \"CFM\"\n", + "trajectory_file = f\"{model}.sqlite\"\n", + "simulation = initialize_simulation(\n", + " jps.CollisionFreeSpeedModelV2(),\n", + " jps.CollisionFreeSpeedModelV2AgentParameters,\n", + " geometry,\n", + " goals,\n", + " positions,\n", + " speeds,\n", + " trajectory_file,\n", + ")\n", + "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", + "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", + "fig1 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + ] + }, + { + "cell_type": "markdown", + "id": "2fbf4d77", + "metadata": {}, + "source": [ + "### AVM Simulation\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6e1657f8", + "metadata": {}, + "outputs": [], + "source": [ + "model = \"AVM\"\n", + "trajectory_file = f\"{model}.sqlite\"\n", + "simulation = initialize_simulation(\n", + " jps.AnticipationVelocityModel(),\n", + " jps.AnticipationVelocityModelAgentParameters,\n", + " geometry,\n", + " goals,\n", + " positions,\n", + " speeds,\n", + " trajectory_file,\n", + ")\n", + "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", + "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", + "fig2 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + ] + }, + { + "cell_type": "markdown", + "id": "2448d825", + "metadata": {}, + "source": [ + "### SFM Simulation\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5a5fdb29", + "metadata": {}, + "outputs": [], + "source": [ + "model = \"SFM\"\n", + "trajectory_file = f\"{model}.sqlite\"\n", + "simulation = initialize_simulation(\n", + " jps.SocialForceModel(),\n", + " jps.SocialForceModelAgentParameters,\n", + " geometry,\n", + " goals,\n", + " positions,\n", + " speeds,\n", + " trajectory_file,\n", + ")\n", + "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", + "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", + "fig3 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + ] + }, + { + "cell_type": "markdown", + "id": "24f23728", + "metadata": {}, + "source": [ + "### GCFM Simulation\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "12c632de", + "metadata": {}, + "outputs": [], + "source": [ + "model = \"GCFM\"\n", + "trajectory_file = f\"{model}.sqlite\"\n", + "simulation = initialize_simulation(\n", + " jps.GeneralizedCentrifugalForceModel(),\n", + " jps.GeneralizedCentrifugalForceModelAgentParameters,\n", + " geometry,\n", + " goals,\n", + " positions,\n", + " speeds,\n", + " trajectory_file,\n", + ")\n", + "times_dict[model] = run_simulation(simulation, max_iterations=5000)\n", + "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", + "fig4 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + ] + }, + { + "cell_type": "markdown", + "id": "a9848f9e", + "metadata": {}, + "source": [ + "### Visualization\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "878ad684", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "widgets_list = [widgets.Output() for _ in range(4)]\n", + "figs = [fig1, fig2, fig3, fig4]\n", + "\n", + "# Display figures in widgets\n", + "for widget, fig in zip(widgets_list, figs):\n", + " with widget:\n", + " fig.show()\n", + "\n", + "# Arrange in two rows\n", + "row1 = widgets.HBox([widgets_list[0], widgets_list[1]])\n", + "row2 = widgets.HBox([widgets_list[2], widgets_list[3]])\n", + "\n", + "# Display the 4 animations\n", + "widgets.VBox([row1, row2])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9926f3b0-d1c4-4e38-9071-71b20298ed25", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "fig = plot_evacuation_times(times_dict)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "478351a0", + "metadata": {}, + "source": [ + "## Scenario 4: Perpendicular Crossing\n", + "\n", + "Two agents move on intersecting paths - one traveling upward and another moving left to right - creating a potential collision point. This tests how models handle collision avoidance when agents approach at right angles.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "86c2b199", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "def create_geometry_scenario4():\n", + " geometry = Polygon([(-6, -6), (6, -6), (6, 6), (-6, 6)])\n", + " return geometry\n", + "\n", + "\n", + "def define_positions_scenario4():\n", + " \"\"\"Define initial positions and desired speeds.\"\"\"\n", + " positions = [(-2, 0), (0, -2)]\n", + " speeds = [1.0, 0.99]\n", + " return positions, speeds\n", + "\n", + "def define_goals_scenario4():\n", + " \"\"\"Define goal polygons.\"\"\"\n", + " goals = [\n", + " Polygon([(5, -2), (6, -2), (6, 2), (5, 2)]),\n", + " Polygon([(-2, 5), (-2, 6), (2, 6), (2, 5)]),\n", + " ]\n", + " return goals\n", + "\n", + "geometry = create_geometry_scenario4()\n", + "positions, speeds = define_positions_scenario4()\n", + "goals = define_goals_scenario4()\n", + "plot_simulation_configuration(geometry, positions, goals)\n", + "times_dict = {}" + ] + }, + { + "cell_type": "markdown", + "id": "29092296", + "metadata": {}, + "source": [ + "### CSM Simulation\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5683d076", + "metadata": {}, + "outputs": [], + "source": [ + "model = \"CFM\"\n", + "trajectory_file = f\"{model}.sqlite\"\n", + "simulation = initialize_simulation(\n", + " jps.CollisionFreeSpeedModelV2(),\n", + " jps.CollisionFreeSpeedModelV2AgentParameters,\n", + " geometry,\n", + " goals,\n", + " positions,\n", + " speeds,\n", + " trajectory_file,\n", + ")\n", + "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", + "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", + "fig1 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + ] + }, + { + "cell_type": "markdown", + "id": "f1767999", + "metadata": {}, + "source": [ + "### AVM Simulation\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9ac17a40", + "metadata": {}, + "outputs": [], + "source": [ + "model = \"AVM\"\n", + "trajectory_file = f\"{model}.sqlite\"\n", + "simulation = initialize_simulation(\n", + " jps.AnticipationVelocityModel(),\n", + " jps.AnticipationVelocityModelAgentParameters,\n", + " geometry,\n", + " goals,\n", + " positions,\n", + " speeds,\n", + " trajectory_file,\n", + ")\n", + "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", + "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", + "fig2 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + ] + }, + { + "cell_type": "markdown", + "id": "d6a75e02", + "metadata": {}, + "source": [ + "### SFM Simulation\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "14e13c6b", + "metadata": {}, + "outputs": [], + "source": [ + "model = \"SFM\"\n", + "trajectory_file = f\"{model}.sqlite\"\n", + "simulation = initialize_simulation(\n", + " jps.SocialForceModel(),\n", + " jps.SocialForceModelAgentParameters,\n", + " geometry,\n", + " goals,\n", + " positions,\n", + " speeds,\n", + " trajectory_file,\n", + ")\n", + "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", + "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", + "fig3 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + ] + }, + { + "cell_type": "markdown", + "id": "cbfbde63", + "metadata": {}, + "source": [ + "### GCFM Simulation\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "20edcdd7", + "metadata": {}, + "outputs": [], + "source": [ + "model = \"GCFM\"\n", + "trajectory_file = f\"{model}.sqlite\"\n", + "simulation = initialize_simulation(\n", + " jps.GeneralizedCentrifugalForceModel(),\n", + " jps.GeneralizedCentrifugalForceModelAgentParameters,\n", + " geometry,\n", + " goals,\n", + " positions,\n", + " speeds,\n", + " trajectory_file,\n", + ")\n", + "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", + "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", + "fig4 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + ] + }, + { + "cell_type": "markdown", + "id": "79db3354", + "metadata": {}, + "source": [ + "### Visualization\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "438d9a5d", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "widgets_list = [widgets.Output() for _ in range(4)]\n", + "figs = [fig1, fig2, fig3, fig4]\n", + "\n", + "# Display figures in widgets\n", + "for widget, fig in zip(widgets_list, figs):\n", + " with widget:\n", + " fig.show()\n", + "\n", + "# Arrange in two rows\n", + "row1 = widgets.HBox([widgets_list[0], widgets_list[1]])\n", + "row2 = widgets.HBox([widgets_list[2], widgets_list[3]])\n", + "\n", + "# Display the 4 animations\n", + "widgets.VBox([row1, row2])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5cfe84e2-4c16-4b44-b4d7-69c83bd662e0", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "fig = plot_evacuation_times(times_dict)\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From e6cf0e083de9283028d0212c2f0706671a0b15a6 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 14 Jan 2025 19:23:00 +0100 Subject: [PATCH 27/52] Update models for anticipation velocity model - Remove range_geometry and strength_geometry - Add new parameter wall_buffer_distance --- .../jupedsim/anticipation_velocity_model.h | 42 +++++-------------- .../src/anticipation_velocity_model.cpp | 26 +++--------- libjupedsim/src/simulation.cpp | 3 +- .../src/AnticipationVelocityModel.cpp | 7 +++- .../src/AnticipationVelocityModelData.hpp | 8 ++-- .../anticipation_velocity_model.cpp | 33 +++++---------- .../models/anticipation_velocity_model.py | 30 ++++--------- 7 files changed, 44 insertions(+), 105 deletions(-) diff --git a/libjupedsim/include/jupedsim/anticipation_velocity_model.h b/libjupedsim/include/jupedsim/anticipation_velocity_model.h index d5b554830..5089f6f44 100644 --- a/libjupedsim/include/jupedsim/anticipation_velocity_model.h +++ b/libjupedsim/include/jupedsim/anticipation_velocity_model.h @@ -114,38 +114,21 @@ JUPEDSIM_API void JPS_AnticipationVelocityModelState_SetReactionTime( double reactionTime); /** - * Read strength geometry repulsion of this agent. + * Write wall buffer distance of this agent. * @param handle of the Agent to access. - * @return strength geometry repulsion of this agent + * @param wallBufferDistance of this agent. */ -JUPEDSIM_API double JPS_AnticipationVelocityModelState_GetStrengthGeometryRepulsion( - JPS_AnticipationVelocityModelState handle); - -/** - * Write strength geometry repulsion of this agent. - * @param handle of the Agent to access. - * @param strengthGeometryRepulsion of this agent. - */ -JUPEDSIM_API void JPS_AnticipationVelocityModelState_SetStrengthGeometryRepulsion( +JUPEDSIM_API void JPS_AnticipationVelocityModelState_SetWallBufferDistance( JPS_AnticipationVelocityModelState handle, - double strengthGeometryRepulsion); - -/** - * Read range geometry repulsion of this agent. - * @param handle of the Agent to access. - * @return range geometry repulsion of this agent - */ -JUPEDSIM_API double JPS_AnticipationVelocityModelState_GetRangeGeometryRepulsion( - JPS_AnticipationVelocityModelState handle); + double wallBufferDistance); /** - * Write strength neighbor repulsion of this agent. + * Read wall buffer distance of this agent. * @param handle of the Agent to access. - * @param rangeGeometryRepulsion of this agent. + * @return wall buffer distance of this agent */ -JUPEDSIM_API void JPS_AnticipationVelocityModelState_SetRangeGeometryRepulsion( - JPS_AnticipationVelocityModelState handle, - double rangeGeometryRepulsion); +JUPEDSIM_API double +JPS_AnticipationVelocityModelState_GetWallBufferDistance(JPS_AnticipationVelocityModelState handle); /** * Read e0 of this agent. @@ -255,14 +238,9 @@ typedef struct JPS_AnticipationVelocityModelAgentParameters { double rangeNeighborRepulsion{0.1}; /** - * Strength of the repulsion from geometry boundaries - */ - double strengthGeometryRepulsion{5.0}; - - /** - * Range of the repulsion from geometry boundaries + * Wall buffer distance to geometry boundaries */ - double rangeGeometryRepulsion{0.02}; + double wallBufferDistance{0.1}; /** * Anticipation time in seconds diff --git a/libjupedsim/src/anticipation_velocity_model.cpp b/libjupedsim/src/anticipation_velocity_model.cpp index d58cd99fc..860415301 100644 --- a/libjupedsim/src/anticipation_velocity_model.cpp +++ b/libjupedsim/src/anticipation_velocity_model.cpp @@ -123,38 +123,22 @@ void JPS_AnticipationVelocityModelState_SetReactionTime( state->reactionTime = reactionTime; } -double JPS_AnticipationVelocityModelState_GetStrengthGeometryRepulsion( +double JPS_AnticipationVelocityModelState_GetWallBufferDistance( JPS_AnticipationVelocityModelState handle) { assert(handle); const auto state = reinterpret_cast(handle); - return state->strengthGeometryRepulsion; + return state->wallBufferDistance; } -void JPS_AnticipationVelocityModelState_SetStrengthGeometryRepulsion( - JPS_AnticipationVelocityModelState handle, - double strengthGeometryRepulsion) -{ - assert(handle); - auto state = reinterpret_cast(handle); - state->strengthGeometryRepulsion = strengthGeometryRepulsion; -} - -double JPS_AnticipationVelocityModelState_GetRangeGeometryRepulsion( - JPS_AnticipationVelocityModelState handle) -{ - assert(handle); - const auto state = reinterpret_cast(handle); - return state->rangeGeometryRepulsion; -} -void JPS_AnticipationVelocityModelState_SetRangeGeometryRepulsion( +void JPS_AnticipationVelocityModelState_SetWallBufferDistance( JPS_AnticipationVelocityModelState handle, - double rangeGeometryRepulsion) + double wallBufferDistance) { assert(handle); auto state = reinterpret_cast(handle); - state->rangeGeometryRepulsion = rangeGeometryRepulsion; + state->wallBufferDistance = wallBufferDistance; } double JPS_AnticipationVelocityModelState_GetTimeGap(JPS_AnticipationVelocityModelState handle) diff --git a/libjupedsim/src/simulation.cpp b/libjupedsim/src/simulation.cpp index aeb7f0dd0..3790a2d10 100644 --- a/libjupedsim/src/simulation.cpp +++ b/libjupedsim/src/simulation.cpp @@ -305,8 +305,7 @@ JPS_AgentId JPS_Simulation_AddAnticipationVelocityModelAgent( AnticipationVelocityModelData{ .strengthNeighborRepulsion = parameters.strengthNeighborRepulsion, .rangeNeighborRepulsion = parameters.rangeNeighborRepulsion, - .strengthGeometryRepulsion = parameters.strengthGeometryRepulsion, - .rangeGeometryRepulsion = parameters.rangeGeometryRepulsion, + .wallBufferDistance = parameters.wallBufferDistance, .anticipationTime = parameters.anticipationTime, .reactionTime = parameters.reactionTime, .velocity = {}, diff --git a/libsimulator/src/AnticipationVelocityModel.cpp b/libsimulator/src/AnticipationVelocityModel.cpp index 392fdf53d..d8dbca245 100644 --- a/libsimulator/src/AnticipationVelocityModel.cpp +++ b/libsimulator/src/AnticipationVelocityModel.cpp @@ -68,7 +68,7 @@ OperationalModelUpdate AnticipationVelocityModel::ComputeNewPosition( } const auto& model = std::get(ped.model); - const double wallBufferDistance = 0.1; // TODO model parameter + const double wallBufferDistance = model.wallBufferDistance; // Wall sliding behavior direction = HandleWallAvoidance( direction, @@ -135,6 +135,11 @@ void AnticipationVelocityModel::CheckModelConstraint( constexpr double rMax = 2.; validateConstraint(r, rMin, rMax, "radius", true); + const auto buff = model.wallBufferDistance; + constexpr double buffMin = 0.; + constexpr double buffMax = 1.; + validateConstraint(buff, buffMin, buffMax, "wallBufferDistance"); + const auto v0 = model.v0; constexpr double v0Min = 0.; constexpr double v0Max = 10.; diff --git a/libsimulator/src/AnticipationVelocityModelData.hpp b/libsimulator/src/AnticipationVelocityModelData.hpp index fe05d131d..c97fbaf33 100644 --- a/libsimulator/src/AnticipationVelocityModelData.hpp +++ b/libsimulator/src/AnticipationVelocityModelData.hpp @@ -7,8 +7,7 @@ struct AnticipationVelocityModelData { double strengthNeighborRepulsion{}; double rangeNeighborRepulsion{}; - double strengthGeometryRepulsion{}; - double rangeGeometryRepulsion{}; + double wallBufferDistance{}; double anticipationTime{1.0}; // t^a double reactionTime{0.3}; // tau Point velocity{}; // v @@ -28,12 +27,11 @@ struct fmt::formatter { return fmt::format_to( ctx.out(), "AnticipationVelocityModel[strengthNeighborRepulsion={}, " - "rangeNeighborRepulsion={}, strengthGeometryRepulsion={}, rangeGeometryRepulsion={}, " + "rangeNeighborRepulsion={}, wallBufferDistance={}, " "timeGap={}, v0={}, radius={}, reactionTime={}, anticipationTime={}, velocity={}])", m.strengthNeighborRepulsion, m.rangeNeighborRepulsion, - m.strengthGeometryRepulsion, - m.rangeGeometryRepulsion, + m.wallBufferDistance, m.timeGap, m.v0, m.radius, diff --git a/python_bindings_jupedsim/anticipation_velocity_model.cpp b/python_bindings_jupedsim/anticipation_velocity_model.cpp index 1985e9c40..13076c491 100644 --- a/python_bindings_jupedsim/anticipation_velocity_model.cpp +++ b/python_bindings_jupedsim/anticipation_velocity_model.cpp @@ -26,8 +26,7 @@ void init_anticipation_velocity_model(py::module_& m) JPS_StageId stage_id, double strengthNeighborRepulsion, double rangeNeighborRepulsion, - double strengthGeometryRepulsion, - double rangeGeometryRepulsion, + double wallBufferDistance, double anticipationTime, double reactionTime) { return JPS_AnticipationVelocityModelAgentParameters{ @@ -39,8 +38,7 @@ void init_anticipation_velocity_model(py::module_& m) radius, strengthNeighborRepulsion, rangeNeighborRepulsion, - strengthGeometryRepulsion, - rangeGeometryRepulsion, + wallBufferDistance, anticipationTime, reactionTime}; }), @@ -53,8 +51,7 @@ void init_anticipation_velocity_model(py::module_& m) py::arg("stage_id"), py::arg("strength_neighbor_repulsion"), py::arg("range_neighbor_repulsion"), - py::arg("strength_geometry_repulsion"), - py::arg("range_geometry_repulsion"), + py::arg("wall_buffer_distance"), py::arg("anticipation_time"), py::arg("reaction_time")) .def("__repr__", [](const JPS_AnticipationVelocityModelAgentParameters& p) { @@ -62,7 +59,7 @@ void init_anticipation_velocity_model(py::module_& m) "position: {}, journey_id: {}, stage_id: {}, " "time_gap: {}, v0: {}, radius: {}", "strength_neighbor_repulsion: {}, range_neighbor_repulsion: {}" - "strength_geometry_repulsion: {}, range_geometry_repulsion: {}" + "wall_buffer_distance: {}" "anticipation_time: {}, reaction_time: {}", intoTuple(p.position), p.journeyId, @@ -72,8 +69,7 @@ void init_anticipation_velocity_model(py::module_& m) p.radius, p.strengthNeighborRepulsion, p.rangeNeighborRepulsion, - p.strengthGeometryRepulsion, - p.rangeGeometryRepulsion, + p.wallBufferDistance, p.anticipationTime, p.reactionTime); }); @@ -136,22 +132,13 @@ void init_anticipation_velocity_model(py::module_& m) w.handle, rangeNeighborRepulsion); }) .def_property( - "strength_geometry_repulsion", + "wall_buffer_distance", [](const JPS_AnticipationVelocityModelState_Wrapper& w) { - return JPS_AnticipationVelocityModelState_GetStrengthGeometryRepulsion(w.handle); + return JPS_AnticipationVelocityModelState_GetWallBufferDistance(w.handle); }, - [](JPS_AnticipationVelocityModelState_Wrapper& w, double strengthGeometryRepulsion) { - JPS_AnticipationVelocityModelState_SetStrengthGeometryRepulsion( - w.handle, strengthGeometryRepulsion); - }) - .def_property( - "range_geometry_repulsion", - [](const JPS_AnticipationVelocityModelState_Wrapper& w) { - return JPS_AnticipationVelocityModelState_GetRangeGeometryRepulsion(w.handle); - }, - [](JPS_AnticipationVelocityModelState_Wrapper& w, double rangeGeometryRepulsion) { - JPS_AnticipationVelocityModelState_SetRangeGeometryRepulsion( - w.handle, rangeGeometryRepulsion); + [](JPS_AnticipationVelocityModelState_Wrapper& w, double wallBufferDistance) { + JPS_AnticipationVelocityModelState_SetWallBufferDistance( + w.handle, wallBufferDistance); }) .def_property( "anticipation_time", diff --git a/python_modules/jupedsim/jupedsim/models/anticipation_velocity_model.py b/python_modules/jupedsim/jupedsim/models/anticipation_velocity_model.py index ae9517499..0b6aad5b0 100644 --- a/python_modules/jupedsim/jupedsim/models/anticipation_velocity_model.py +++ b/python_modules/jupedsim/jupedsim/models/anticipation_velocity_model.py @@ -63,8 +63,7 @@ class AnticipationVelocityModelAgentParameters: stage_id: Id of the stage the agent targets. strength_neighbor_repulsion: Strength of the repulsion from neighbors range_neighbor_repulsion: Range of the repulsion from neighbors - strength_geometry_repulsion: Strength of the repulsion from geometry boundaries - range_geometry_repulsion: Range of the repulsion from geometry boundaries + wall_buffer_distance: Buffer distance of agents to the walls. anticipation_time: Anticipation time of an agent. reaction_time: reaction time of an agent to change its direction. """ @@ -77,8 +76,7 @@ class AnticipationVelocityModelAgentParameters: stage_id: int = 0 strength_neighbor_repulsion: float = 8.0 range_neighbor_repulsion: float = 0.1 - strength_geometry_repulsion: float = 5.0 - range_geometry_repulsion: float = 0.02 + wall_buffer_distance: float = 0.1 anticipation_time: float = 1.0 reaction_time: float = 0.3 @@ -94,8 +92,7 @@ def as_native( stage_id=self.stage_id, strength_neighbor_repulsion=self.strength_neighbor_repulsion, range_neighbor_repulsion=self.range_neighbor_repulsion, - strength_geometry_repulsion=self.strength_geometry_repulsion, - range_geometry_repulsion=self.range_geometry_repulsion, + wall_buffer_distance=self.wall_buffer_distance, anticipation_time=self.anticipation_time, reaction_time=self.reaction_time, ) @@ -150,22 +147,13 @@ def range_neighbor_repulsion(self, range_neighbor_repulsion): self._obj.range_neighbor_repulsion = range_neighbor_repulsion @property - def strength_geometry_repulsion(self) -> float: - """Strength of the repulsion from geometry boundaries of this agent.""" - return self._obj.strength_geometry_repulsion + def wall_buffer_distance(self): + """Wall buffer distance of agent to walls.""" + return self._obj.wall_buffer_distance - @strength_geometry_repulsion.setter - def strength_geometry_repulsion(self, strength_geometry_repulsion): - self._obj.strength_geometry_repulsion = strength_geometry_repulsion - - @property - def range_geometry_repulsion(self) -> float: - """Range of the repulsion from geometry boundaries of this agent.""" - return self._obj.range_geometry_repulsion - - @range_geometry_repulsion.setter - def range_geometry_repulsion(self, range_geometry_repulsion): - self._obj.range_geometry_repulsion = range_geometry_repulsion + @wall_buffer_distance.setter + def wall_buffer_distance(self, wall_buffer_distance): + self._obj.wall_buffer_distance = wall_buffer_distance @property def anticipation_time(self) -> float: From 6f4150814d00545539cfc5ae3aecea44d9a15443 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 14 Jan 2025 19:26:24 +0100 Subject: [PATCH 28/52] Update notebook with time plots --- notebooks/model_comparison.ipynb | 51 +++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/notebooks/model_comparison.ipynb b/notebooks/model_comparison.ipynb index fd9d10d22..82005f3dc 100644 --- a/notebooks/model_comparison.ipynb +++ b/notebooks/model_comparison.ipynb @@ -60,8 +60,6 @@ "import jupedsim as jps\n", "import matplotlib.pyplot as plt\n", "import pedpy\n", - "import shapely\n", - "from matplotlib.patches import Circle\n", "from shapely import Polygon\n", "from jupedsim.internal.notebook_utils import animate, read_sqlite_file\n", "from shapely.ops import unary_union\n", @@ -71,7 +69,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 83, "id": "b982aeaf-a056-4870-bf96-4213db17ddcd", "metadata": { "tags": [ @@ -83,6 +81,7 @@ "def initialize_simulation(\n", " model, agent_parameters, geometry, goals, positions, speeds, trajectory_file\n", "):\n", + "\n", " simulation = jps.Simulation(\n", " model=model,\n", " geometry=geometry,\n", @@ -135,34 +134,37 @@ " axes = pedpy.plot_walkable_area(walkable_area=walkable_area)\n", " for exit_area in exit_areas:\n", " axes.fill(*exit_area.exterior.xy, color=\"indianred\")\n", - " \n", + "\n", " axes.scatter(*zip(*starting_positions), label=\"Starting Position\")\n", " axes.set_xlabel(\"x/m\")\n", " axes.set_ylabel(\"y/m\")\n", " axes.set_aspect(\"equal\")\n", " axes.grid(True, alpha=0.3)\n", "\n", + "\n", "def plot_evacuation_times(times_dict, figsize=(10, 6)):\n", " \"\"\"\n", " Plot evacuation times for different pedestrian models.\n", " \"\"\"\n", " fig = plt.figure(figsize=figsize)\n", - " \n", - " # Create bar chart\n", + "\n", " bars = plt.bar(list(times_dict.keys()), list(times_dict.values()))\n", - " \n", - " # Customize the plot\n", - " plt.title('Evacuation Times by Model')\n", - " plt.ylabel('Time (seconds)')\n", - " plt.grid(axis='y', linestyle='--', alpha=0.7)\n", - " \n", + "\n", + " plt.title(\"Evacuation Times by Model\")\n", + " plt.ylabel(\"Time (seconds)\")\n", + " plt.grid(axis=\"y\", linestyle=\"--\", alpha=0.3)\n", + "\n", " # Add value labels on top of each bar\n", " for bar in bars:\n", " height = bar.get_height()\n", - " plt.text(bar.get_x() + bar.get_width()/2., height,\n", - " f'{height:.1f}s',\n", - " ha='center', va='bottom')\n", - " \n", + " plt.text(\n", + " bar.get_x() + bar.get_width() / 2.0,\n", + " height,\n", + " f\"{height:.1f}s\",\n", + " ha=\"center\",\n", + " va=\"bottom\",\n", + " )\n", + "\n", " plt.tight_layout()\n", " return fig\n", "\n", @@ -231,6 +233,7 @@ " ]\n", " return goals\n", "\n", + "\n", "geometry = create_geometry_scenario1()\n", "goals = define_goals_scenario1()\n", "positions, speeds = define_positions_scenario1()\n", @@ -459,6 +462,7 @@ " ]\n", " return goals\n", "\n", + "\n", "geometry = create_geometry_scenario2()\n", "positions, speeds = define_positions_scenario2()\n", "goals = define_goals_scenario2()\n", @@ -687,6 +691,7 @@ " ]\n", " return goals\n", "\n", + "\n", "geometry = create_geometry_scenario3()\n", "positions, speeds = define_positions_scenario3()\n", "goals = define_goals_scenario3()\n", @@ -725,6 +730,16 @@ "fig1 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "6daeafcb-cafc-43ed-932a-a91e6e0ad42e", + "metadata": {}, + "outputs": [], + "source": [ + "print(times_dict)" + ] + }, { "cell_type": "markdown", "id": "2fbf4d77", @@ -900,6 +915,7 @@ " speeds = [1.0, 0.99]\n", " return positions, speeds\n", "\n", + "\n", "def define_goals_scenario4():\n", " \"\"\"Define goal polygons.\"\"\"\n", " goals = [\n", @@ -908,6 +924,7 @@ " ]\n", " return goals\n", "\n", + "\n", "geometry = create_geometry_scenario4()\n", "positions, speeds = define_positions_scenario4()\n", "goals = define_goals_scenario4()\n", @@ -1092,7 +1109,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": ".vnenv", "language": "python", "name": "python3" }, From 9cc1865eaa28f7e4abbc5031ed0cee6d2ee650fc Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 14 Jan 2025 20:02:31 +0100 Subject: [PATCH 29/52] Add documentation for AVM --- docs/source/pedestrian_models/index.rst | 42 +++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/docs/source/pedestrian_models/index.rst b/docs/source/pedestrian_models/index.rst index 1a07db2ed..1e168c910 100644 --- a/docs/source/pedestrian_models/index.rst +++ b/docs/source/pedestrian_models/index.rst @@ -7,6 +7,7 @@ models. Below is a list of all the models that are currently available. Please refer to the links in the respective section for a detailed discussion of the respective model. + ************************** Collision Free Speed Model ************************** @@ -44,6 +45,47 @@ available on `PedestrianDynamics`_. The original publication can be found at https://arxiv.org/abs/1512.05597 +************************** +Anticipation Velocity Model +************************** + +The anticipation velocity model (AVM) is a mathematical approach for pedestrian +dynamics that prevents collisions through anticipatory behavior. The model divides +anticipation into three components: situation perception, future prediction, and +strategy selection. +Building upon the collision-free speed model (CSM), AVM determines agent movement +through exponential repulsion from nearby agents. Unlike CSM, the influence +direction is orthogonal to the agent's desired direction. +Repulsion strength is affected by agents within the perception field - +specifically, those in the union of two half-planes where the agent moves or +intends to move. Agents adjust their speed based on anticipated distance to the +nearest neighbor in their headway, enabling navigation through congested areas +without overlap. +The model incorporates a reaction time factor to adjust the turning process rate +from the current to the new direction. Walls are treated as gliding surfaces: +when an agent is within critical distance of a wall and moving toward it, their +direction is projected parallel to the wall surface. +Movement calculation occurs in two steps: first, combining the desired direction +with neighbor influences, then adjusting for wall interactions when necessary. +Walls do not influence the speed of agents, only their direction. + +The anticipation velocity model takes into account the length of the agent, +which determines the required space for movement, and the maximum achievable +speed of the agent. This simplified and computationally efficient model aims to +mirror real-world pedestrian behaviors while maintaining smooth movement +dynamics. + +The parameters of the anticipation velocity model can be defined per-agent. + +In :class:`~jupedsim.models.AnticipationVelocityModel` neighbor and wall +parameters are per-agent parameters that can be set individually via +:class:`~jupedsim.models.AnticipationVelocityModelAgentParameters` and can be +changed at any time. + + +The original publication can be found at https://doi.org/10.1016/j.trc.2021.103464 + + *********************************** Generalized Centrifugal Force Model *********************************** From f2d88a77e33cbad710a04f17238f115177b85218 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 14 Jan 2025 20:03:18 +0100 Subject: [PATCH 30/52] link notebook to documentation --- docs/source/notebooks/model_comparison.ipynb | 1 + 1 file changed, 1 insertion(+) create mode 120000 docs/source/notebooks/model_comparison.ipynb diff --git a/docs/source/notebooks/model_comparison.ipynb b/docs/source/notebooks/model_comparison.ipynb new file mode 120000 index 000000000..e0a5b3a78 --- /dev/null +++ b/docs/source/notebooks/model_comparison.ipynb @@ -0,0 +1 @@ +../../../notebooks/model_comparison.ipynb \ No newline at end of file From 920259f591213ed79a875b0d5f63f2d9a201097f Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 14 Jan 2025 20:52:12 +0100 Subject: [PATCH 31/52] Update model notebook --- notebooks/model_comparison.ipynb | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/notebooks/model_comparison.ipynb b/notebooks/model_comparison.ipynb index 82005f3dc..8337ba7c3 100644 --- a/notebooks/model_comparison.ipynb +++ b/notebooks/model_comparison.ipynb @@ -69,7 +69,7 @@ }, { "cell_type": "code", - "execution_count": 83, + "execution_count": null, "id": "b982aeaf-a056-4870-bf96-4213db17ddcd", "metadata": { "tags": [ @@ -449,7 +449,7 @@ " ]\n", " speeds = [\n", " 1.0,\n", - " 0.5,\n", + " 0.0,\n", " ]\n", " return positions, speeds\n", "\n", @@ -589,7 +589,7 @@ " speeds,\n", " trajectory_file,\n", ")\n", - "times_dict[model] = run_simulation(simulation, max_iterations=5000)\n", + "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", "fig4 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" ] @@ -629,21 +629,6 @@ "widgets.VBox([row1, row2])" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "a4f33439-71a1-450a-aee2-ab102db7c787", - "metadata": { - "tags": [ - "hide-input" - ] - }, - "outputs": [], - "source": [ - "fig = plot_evacuation_times(times_dict)\n", - "plt.show()" - ] - }, { "cell_type": "markdown", "id": "6f9f6b1f", @@ -1109,7 +1094,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".vnenv", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, From 3ca16f1d94a548ffe1385fd805ea294a3b1dc07c Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 14 Jan 2025 21:28:45 +0100 Subject: [PATCH 32/52] Add requirement for notebook --- docs/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/requirements.txt b/docs/requirements.txt index cc5d4b0ce..bf50f49ef 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -14,3 +14,4 @@ plotly-express numpy pandas pedpy +ipywidgets From 6d37d3bde52c2a5ac44a7a8dac7633fc915e43bc Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Tue, 14 Jan 2025 22:52:05 +0100 Subject: [PATCH 33/52] rename notebook and add it to index --- docs/source/notebooks/index.rst | 1 + docs/source/notebooks/model-comparison.ipynb | 1 + docs/source/notebooks/model_comparison.ipynb | 1 - notebooks/{model_comparison.ipynb => model-comparison.ipynb} | 0 4 files changed, 2 insertions(+), 1 deletion(-) create mode 120000 docs/source/notebooks/model-comparison.ipynb delete mode 120000 docs/source/notebooks/model_comparison.ipynb rename notebooks/{model_comparison.ipynb => model-comparison.ipynb} (100%) diff --git a/docs/source/notebooks/index.rst b/docs/source/notebooks/index.rst index b21f21c9b..8f85933bd 100644 --- a/docs/source/notebooks/index.rst +++ b/docs/source/notebooks/index.rst @@ -5,6 +5,7 @@ Notebooks .. toctree:: :maxdepth: 1 + model-comparison corner double-bottleneck journey diff --git a/docs/source/notebooks/model-comparison.ipynb b/docs/source/notebooks/model-comparison.ipynb new file mode 120000 index 000000000..0562bbf2d --- /dev/null +++ b/docs/source/notebooks/model-comparison.ipynb @@ -0,0 +1 @@ +../../../notebooks/model-comparison.ipynb \ No newline at end of file diff --git a/docs/source/notebooks/model_comparison.ipynb b/docs/source/notebooks/model_comparison.ipynb deleted file mode 120000 index e0a5b3a78..000000000 --- a/docs/source/notebooks/model_comparison.ipynb +++ /dev/null @@ -1 +0,0 @@ -../../../notebooks/model_comparison.ipynb \ No newline at end of file diff --git a/notebooks/model_comparison.ipynb b/notebooks/model-comparison.ipynb similarity index 100% rename from notebooks/model_comparison.ipynb rename to notebooks/model-comparison.ipynb From 8fbc35d7bde8ca8c63f5a2896183922f20e13c1e Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Wed, 15 Jan 2025 12:39:22 +0100 Subject: [PATCH 34/52] Add more explanatory context to the notebook - Change visualisation from grid to simple to fit the layout of documentation - remove dependency Remove requirement --- docs/requirements.txt | 1 - notebooks/model-comparison.ipynb | 189 +++++++------------------------ 2 files changed, 40 insertions(+), 150 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index bf50f49ef..cc5d4b0ce 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -14,4 +14,3 @@ plotly-express numpy pandas pedpy -ipywidgets diff --git a/notebooks/model-comparison.ipynb b/notebooks/model-comparison.ipynb index 8337ba7c3..b0a48b7b2 100644 --- a/notebooks/model-comparison.ipynb +++ b/notebooks/model-comparison.ipynb @@ -11,8 +11,20 @@ "\n", "This notebook compares four pedestrian dynamics models by simulating agent behavior in a structured environment. Using simplified scenarios, we analyze how each model handles navigation, obstacle avoidance, and agent interactions. This comparison reveals the strengths and weaknesses of each approach, helping inform model selection when using JuPedSim.\n", "\n", - "> **Note:** \n", - "> All models are utilized with their default parameter settings as defined in **JuPedSim**.\n", + "When choosing a pedestrian dynamics model in JuPedSim, the decision largely depends on the specific scenario you want to simulate or the behavior you want to reproduce. The available models can be divided into two main categories: force-based and velocity-based models, each with their own strengths and limitations.\n", + "\n", + "Force-based models, which include the Social Force Model (SFM) and the Generalized Centrifugal Force Model (GCFM), excel at simulating physical interactions between pedestrians. These models are particularly effective at capturing pushing behavior in dense crowds, making them ideal for evacuation scenarios or situations where physical contact between pedestrians is common. The GCFM offers some improvements over the basic SFM, particularly in handling body shape effects.\n", + "\n", + "On the other hand, velocity-based models like the Collision-Free Model (CFM) and the Anticipation Velocity Model (AVM) are better suited for normal walking situations where collision avoidance is the primary concern. These models typically produce smoother, more realistic trajectories in regular-density scenarios. The AVM, in particular, stands out for its superior collision avoidance capabilities and ability to reproduce lane formation behavior, as demonstrated in [recent research](https://doi.org/10.1016/j.trc.2021.103464).\n", + "\n", + "When it comes to computational efficiency, velocity-based models generally have an advantage. The CFM offers the fastest execution times, while the AVM provides a good balance between computational efficiency and realistic behavior simulation. Force-based models, while more computationally intensive, are necessary when accurate physical interaction modeling is crucial.\n", + "\n", + "The choice of model ultimately comes down to your specific requirements. If you're simulating emergency evacuations or very crowded environments where physical interactions are important, a force-based model like GCFM would be appropriate. For typical pedestrian scenarios where smooth navigation and realistic avoidance behavior are priority, the AVM would be the better choice. In cases where computational resources are limited and physical interactions are not critical, the CFM can provide adequate results.\n", + "\n", + "The key is to understand that no single model is universally superior – each has its place depending on the specific requirements of your simulation scenario.\n", + "\n", + "\n", + "**So as a final facit, which model to use? The answer is: it depends.**\n", "\n", "## Models Under Investigation\n", "\n", @@ -28,6 +40,9 @@ "4. [**Generalized Centrifugal Force Model (GCFM):**](https://pedestriandynamics.org/models/generalized_centrifugal_force_model/) \n", " An enhanced force-based model where agents experience centrifugal forces to better simulate realistic avoidance behavior.\n", "\n", + "> **Note:** \n", + "> All models are utilized with their default parameter settings as defined in **JuPedSim**.\n", + "\n", "## Simulation Workflow\n", "\n", "- **Environment Setup:**\n", @@ -63,7 +78,6 @@ "from shapely import Polygon\n", "from jupedsim.internal.notebook_utils import animate, read_sqlite_file\n", "from shapely.ops import unary_union\n", - "import ipywidgets as widgets\n", "import pedpy" ] }, @@ -175,7 +189,10 @@ " ):\n", " simulation.iterate()\n", " print(f\"Evacuation time: {simulation.elapsed_time():.2f} s\")\n", - " return simulation.elapsed_time()" + " return simulation.elapsed_time()\n", + "\n", + "width=600\n", + "height=600" ] }, { @@ -269,7 +286,7 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=5000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "fig1 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" ] }, { @@ -300,7 +317,7 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=5000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "fig2 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" ] }, { @@ -331,7 +348,7 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=5000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "fig3 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" ] }, { @@ -362,7 +379,7 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=5000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "fig4 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" ] }, { @@ -370,34 +387,7 @@ "id": "884203af-0af3-474e-a4a9-646ab3988478", "metadata": {}, "source": [ - "### Visualization\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8ff1110a-b542-4966-93b7-a494a7b5a767", - "metadata": { - "tags": [ - "hide-input" - ] - }, - "outputs": [], - "source": [ - "widgets_list = [widgets.Output() for _ in range(4)]\n", - "figs = [fig1, fig2, fig3, fig4]\n", - "\n", - "# Display figures in widgets\n", - "for widget, fig in zip(widgets_list, figs):\n", - " with widget:\n", - " fig.show()\n", - "\n", - "# Arrange in two rows\n", - "row1 = widgets.HBox([widgets_list[0], widgets_list[1]])\n", - "row2 = widgets.HBox([widgets_list[2], widgets_list[3]])\n", - "\n", - "# Display the 4 animations\n", - "widgets.VBox([row1, row2])" + "### Evacuation times\n" ] }, { @@ -498,7 +488,7 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "fig1 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" ] }, { @@ -529,7 +519,7 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "fig2 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" ] }, { @@ -560,7 +550,7 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "fig3 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" ] }, { @@ -591,42 +581,7 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "fig4 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" - ] - }, - { - "cell_type": "markdown", - "id": "4da400b6-72c2-4034-a10b-a4370eda8232", - "metadata": {}, - "source": [ - "### Visualization\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9a094237-a8b2-49ae-96a9-013f4fe397eb", - "metadata": { - "tags": [ - "hide-input" - ] - }, - "outputs": [], - "source": [ - "widgets_list = [widgets.Output() for _ in range(4)]\n", - "figs = [fig1, fig2, fig3, fig4]\n", - "\n", - "# Display figures in widgets\n", - "for widget, fig in zip(widgets_list, figs):\n", - " with widget:\n", - " fig.show()\n", - "\n", - "# Arrange in two rows\n", - "row1 = widgets.HBox([widgets_list[0], widgets_list[1]])\n", - "row2 = widgets.HBox([widgets_list[2], widgets_list[3]])\n", - "\n", - "# Display the 4 animations\n", - "widgets.VBox([row1, row2])" + "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" ] }, { @@ -712,17 +667,7 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "fig1 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6daeafcb-cafc-43ed-932a-a91e6e0ad42e", - "metadata": {}, - "outputs": [], - "source": [ - "print(times_dict)" + "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" ] }, { @@ -753,7 +698,7 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "fig2 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" ] }, { @@ -784,7 +729,7 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "fig3 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" ] }, { @@ -815,7 +760,7 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=5000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "fig4 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" ] }, { @@ -823,34 +768,7 @@ "id": "a9848f9e", "metadata": {}, "source": [ - "### Visualization\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "878ad684", - "metadata": { - "tags": [ - "hide-input" - ] - }, - "outputs": [], - "source": [ - "widgets_list = [widgets.Output() for _ in range(4)]\n", - "figs = [fig1, fig2, fig3, fig4]\n", - "\n", - "# Display figures in widgets\n", - "for widget, fig in zip(widgets_list, figs):\n", - " with widget:\n", - " fig.show()\n", - "\n", - "# Arrange in two rows\n", - "row1 = widgets.HBox([widgets_list[0], widgets_list[1]])\n", - "row2 = widgets.HBox([widgets_list[2], widgets_list[3]])\n", - "\n", - "# Display the 4 animations\n", - "widgets.VBox([row1, row2])" + "### Evacuation times" ] }, { @@ -945,7 +863,7 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "fig1 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" ] }, { @@ -976,7 +894,7 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "fig2 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" ] }, { @@ -1007,7 +925,7 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "fig3 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" ] }, { @@ -1038,7 +956,7 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "fig4 = animate(trajectories, walkable_area, title_note=model, every_nth_frame=5)" + "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" ] }, { @@ -1046,34 +964,7 @@ "id": "79db3354", "metadata": {}, "source": [ - "### Visualization\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "438d9a5d", - "metadata": { - "tags": [ - "hide-input" - ] - }, - "outputs": [], - "source": [ - "widgets_list = [widgets.Output() for _ in range(4)]\n", - "figs = [fig1, fig2, fig3, fig4]\n", - "\n", - "# Display figures in widgets\n", - "for widget, fig in zip(widgets_list, figs):\n", - " with widget:\n", - " fig.show()\n", - "\n", - "# Arrange in two rows\n", - "row1 = widgets.HBox([widgets_list[0], widgets_list[1]])\n", - "row2 = widgets.HBox([widgets_list[2], widgets_list[3]])\n", - "\n", - "# Display the 4 animations\n", - "widgets.VBox([row1, row2])" + "### Evacuation times" ] }, { From 354da4bfd6fb42f8585871a883f48faffb9e0acc Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Wed, 15 Jan 2025 14:11:43 +0100 Subject: [PATCH 35/52] Add tests for AVM and update AVM-parameters contraints --- .../src/AnticipationVelocityModel.cpp | 24 +- .../src/AnticipationVelocityModelData.hpp | 8 +- systemtest/test_model_constraints.py | 443 ++++++++++++++++++ systemtest/test_model_properties.py | 11 +- 4 files changed, 473 insertions(+), 13 deletions(-) diff --git a/libsimulator/src/AnticipationVelocityModel.cpp b/libsimulator/src/AnticipationVelocityModel.cpp index d8dbca245..10548c815 100644 --- a/libsimulator/src/AnticipationVelocityModel.cpp +++ b/libsimulator/src/AnticipationVelocityModel.cpp @@ -120,6 +120,7 @@ Point AnticipationVelocityModel::UpdateDirection(const GenericAgent& ped, const updatedDirection = actualDirection + directionDerivative * dt; } + return updatedDirection.Normalized(); } @@ -135,10 +136,22 @@ void AnticipationVelocityModel::CheckModelConstraint( constexpr double rMax = 2.; validateConstraint(r, rMin, rMax, "radius", true); + const auto strengthNeighborRepulsion = model.strengthNeighborRepulsion; + constexpr double snMin = 0.; + constexpr double snMax = 20.; + validateConstraint(strengthNeighborRepulsion, snMin, snMax, "strengthNeighborRepulsion", false); + + + const auto rangeNeighborRepulsion = model.rangeNeighborRepulsion; + constexpr double rnMin = 0.; + constexpr double rnMax = 5.; + validateConstraint(rangeNeighborRepulsion, rnMin, rnMax, "rangeNeighborRepulsion", true); + + const auto buff = model.wallBufferDistance; constexpr double buffMin = 0.; constexpr double buffMax = 1.; - validateConstraint(buff, buffMin, buffMax, "wallBufferDistance"); + validateConstraint(buff, buffMin, buffMax, "wallBufferDistance", false); const auto v0 = model.v0; constexpr double v0Min = 0.; @@ -146,9 +159,9 @@ void AnticipationVelocityModel::CheckModelConstraint( validateConstraint(v0, v0Min, v0Max, "v0"); const auto timeGap = model.timeGap; - constexpr double timeGapMin = 0.1; + constexpr double timeGapMin = 0.; constexpr double timeGapMax = 10.; - validateConstraint(timeGap, timeGapMin, timeGapMax, "timeGap"); + validateConstraint(timeGap, timeGapMin, timeGapMax, "timeGap", true); const auto anticipationTime = model.anticipationTime; constexpr double anticipationTimeMin = 0.0; @@ -156,9 +169,10 @@ void AnticipationVelocityModel::CheckModelConstraint( validateConstraint(anticipationTime, anticipationTimeMin, anticipationTimeMax, "anticipationTime"); const auto reactionTime = model.reactionTime; - constexpr double reactionTimeMin = 0.01; + constexpr double reactionTimeMin = 0.0; constexpr double reactionTimeMax = 1.0; - validateConstraint(reactionTime, reactionTimeMin, reactionTimeMax, "reactionTime"); + validateConstraint(reactionTime, reactionTimeMin, reactionTimeMax, "reactionTime", true); + const auto neighbors = neighborhoodSearch.GetNeighboringAgents(agent.pos, 2); for(const auto& neighbor : neighbors) { diff --git a/libsimulator/src/AnticipationVelocityModelData.hpp b/libsimulator/src/AnticipationVelocityModelData.hpp index c97fbaf33..8597aa8d5 100644 --- a/libsimulator/src/AnticipationVelocityModelData.hpp +++ b/libsimulator/src/AnticipationVelocityModelData.hpp @@ -7,10 +7,10 @@ struct AnticipationVelocityModelData { double strengthNeighborRepulsion{}; double rangeNeighborRepulsion{}; - double wallBufferDistance{}; - double anticipationTime{1.0}; // t^a - double reactionTime{0.3}; // tau - Point velocity{}; // v + double wallBufferDistance{}; // buff distance of agent to wall + double anticipationTime{1.0}; // anticipation time + double reactionTime{0.3}; // reaction time to update direction + Point velocity{}; double timeGap{1.06}; double v0{1.2}; double radius{0.15}; diff --git a/systemtest/test_model_constraints.py b/systemtest/test_model_constraints.py index d59cf242f..2a6000699 100644 --- a/systemtest/test_model_constraints.py +++ b/systemtest/test_model_constraints.py @@ -605,3 +605,446 @@ def test_generalized_centrifugal_force_model_can_not_add_agent_too_close_to_wall b_max=b_max, ) ) + + +@pytest.fixture +def square_room_100x100_avm(): + simulation = jps.Simulation( + model=jps.AnticipationVelocityModel(), + geometry=[(-50, -50), (50, -50), (50, 50), (-50, 50)], + ) + + exit_id = simulation.add_exit_stage([(49, -3), (49, 3), (50, 3), (50, -3)]) + + journey = jps.JourneyDescription([exit_id]) + journey_id = simulation.add_journey(journey) + agent_position = (0, 0) + + return simulation, journey_id, exit_id, agent_position + + +@pytest.mark.parametrize("strength", [*np.arange(0.1, 10, 1)]) +def test_anticipation_velocity_model_can_set_strength_neighbor_repulsion( + square_room_100x100_avm, strength +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + strength_neighbor_repulsion=strength, + ) + ) + + +def test_anticipation_velocity_model_can_not_set_strength_neighbor_repulsion_too_small( + square_room_100x100_avm, +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + with pytest.raises( + RuntimeError, + match=r"Model constraint violation: strengthNeighborRepulsion -0.1 .*", + ): + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + strength_neighbor_repulsion=-0.1, + ) + ) + + +def test_anticipation_velocity_model_can_not_set_strength_neighbor_repulsion_too_large( + square_room_100x100_avm, +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + with pytest.raises( + RuntimeError, + match=r"Model constraint violation: strengthNeighborRepulsion 20.1 .*", + ): + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + strength_neighbor_repulsion=20.1, + ) + ) + + +@pytest.mark.parametrize("range_repulsion", [*np.arange(0.1, 5, 1)]) +def test_anticipation_velocity_model_can_set_range_neighbor_repulsion( + square_room_100x100_avm, range_repulsion +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + range_neighbor_repulsion=range_repulsion, + ) + ) + + +def test_anticipation_velocity_model_can_not_set_range_neighbor_repulsion_too_small( + square_room_100x100_avm, +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + with pytest.raises( + RuntimeError, + match=r"Model constraint violation: rangeNeighborRepulsion 0 .*", + ): + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + range_neighbor_repulsion=0, + ) + ) + + +def test_anticipation_velocity_model_can_not_set_range_neighbor_repulsion_too_large( + square_room_100x100_avm, +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + with pytest.raises( + RuntimeError, + match=r"Model constraint violation: rangeNeighborRepulsion 5.1 .*", + ): + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + range_neighbor_repulsion=5.1, + ) + ) + + +@pytest.mark.parametrize("wall_buffer", [*np.arange(0.1, 1, 0.2)]) +def test_anticipation_velocity_model_can_set_wall_buffer_distance( + square_room_100x100_avm, wall_buffer +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + wall_buffer_distance=wall_buffer, + ) + ) + + +def test_anticipation_velocity_model_can_not_set_wall_buffer_distance_too_small( + square_room_100x100_avm, +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + with pytest.raises( + RuntimeError, + match=r"Model constraint violation: wallBufferDistance -0.1 .*", + ): + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + wall_buffer_distance=-0.1, + ) + ) + + +def test_anticipation_velocity_model_can_not_set_wall_buffer_distance_too_large( + square_room_100x100_avm, +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + with pytest.raises( + RuntimeError, + match=r"Model constraint violation: wallBufferDistance 2.1 .*", + ): + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + wall_buffer_distance=2.1, + ) + ) + + +@pytest.mark.parametrize("anticipation_time", [*np.arange(0.1, 5, 0.5)]) +def test_anticipation_velocity_model_can_set_anticipation_time( + square_room_100x100_avm, anticipation_time +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + anticipation_time=anticipation_time, + ) + ) + + +def test_anticipation_velocity_model_can_not_set_anticipation_time_too_small( + square_room_100x100_avm, +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + with pytest.raises( + RuntimeError, + match=r"Model constraint violation: anticipationTime -0.1 .*", + ): + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + anticipation_time=-0.1, + ) + ) + + +def test_anticipation_velocity_model_can_not_set_anticipation_time_too_large( + square_room_100x100_avm, +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + with pytest.raises( + RuntimeError, + match=r"Model constraint violation: anticipationTime 5.1 .*", + ): + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + anticipation_time=5.1, + ) + ) + + +@pytest.mark.parametrize("reaction_time", [*np.arange(0.1, 1, 0.2)]) +def test_anticipation_velocity_model_can_set_reaction_time( + square_room_100x100_avm, reaction_time +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + reaction_time=reaction_time, + ) + ) + + +def test_anticipation_velocity_model_can_not_set_reaction_time_too_small( + square_room_100x100_avm, +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + with pytest.raises( + RuntimeError, match=r"Model constraint violation: reactionTime 0 .*" + ): + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + reaction_time=0, + ) + ) + + +def test_anticipation_velocity_model_can_not_set_reaction_time_too_large( + square_room_100x100_avm, +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + with pytest.raises( + RuntimeError, match=r"Model constraint violation: reactionTime 2.1 .*" + ): + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + reaction_time=2.1, + ) + ) + + +@pytest.mark.parametrize("time_gap", [*np.arange(0.1, 10, 1)]) +def test_anticipation_velocity_model_can_set_time_gap( + square_room_100x100_avm, time_gap +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + time_gap=time_gap, + ) + ) + + +def test_anticipation_velocity_model_can_not_set_time_gap_too_small( + square_room_100x100_avm, +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + with pytest.raises( + RuntimeError, match=r"Model constraint violation: timeGap 0 .*" + ): + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + time_gap=0, + ) + ) + + +def test_anticipation_velocity_model_can_not_set_time_gap_too_large( + square_room_100x100_avm, +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + with pytest.raises( + RuntimeError, match=r"Model constraint violation: timeGap 10.1 .*" + ): + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + time_gap=10.1, + ) + ) + + +@pytest.mark.parametrize("v0", [*np.arange(0.1, 10, 1)]) +def test_anticipation_velocity_model_can_set_v0(square_room_100x100_avm, v0): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + v0=v0, + ) + ) + + +def test_anticipation_velocity_model_can_not_set_v0_too_small( + square_room_100x100_avm, +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + with pytest.raises( + RuntimeError, match=r"Model constraint violation: v0 -0.1 .*" + ): + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + v0=-0.1, + ) + ) + + +def test_anticipation_velocity_model_can_not_set_v0_too_large( + square_room_100x100_avm, +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + with pytest.raises( + RuntimeError, match=r"Model constraint violation: v0 10.1 .*" + ): + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + v0=10.1, + ) + ) + + +@pytest.mark.parametrize("radius", [*np.arange(0.1, 2, 0.2)]) +def test_anticipation_velocity_model_can_set_radius( + square_room_100x100_avm, radius +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + radius=radius, + ) + ) + + +def test_anticipation_velocity_model_can_not_set_radius_too_small( + square_room_100x100_avm, +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + with pytest.raises( + RuntimeError, match=r"Model constraint violation: radius 0 .*" + ): + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + radius=0, + ) + ) + + +def test_anticipation_velocity_model_can_not_set_radius_too_large( + square_room_100x100_avm, +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + with pytest.raises( + RuntimeError, match=r"Model constraint violation: radius 2.1 .*" + ): + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=agent_position, + journey_id=journey_id, + stage_id=exit_id, + radius=2.1, + ) + ) + + +@pytest.mark.parametrize("radius", [*np.arange(0.1, 0.5, 0.1)]) +def test_anticipation_velocity_model_can_not_add_agent_too_close_to_wall( + square_room_100x100_avm, + radius, +): + simulation, journey_id, exit_id, agent_position = square_room_100x100_avm + + with pytest.raises( + RuntimeError, + match=r"Model constraint violation: Agent (.+) too close to geometry boundaries, distance .*", + ): + simulation.add_agent( + jps.AnticipationVelocityModelAgentParameters( + position=(50 - (0.99 * radius), 0), + journey_id=journey_id, + stage_id=exit_id, + radius=radius, + ) + ) diff --git a/systemtest/test_model_properties.py b/systemtest/test_model_properties.py index 609da4cf2..92b0d7f57 100644 --- a/systemtest/test_model_properties.py +++ b/systemtest/test_model_properties.py @@ -120,11 +120,14 @@ def test_set_model_parameters_anticipation_velocity_model( sim.agent(agent_id).model.range_neighbor_repulsion = 6.0 assert sim.agent(agent_id).model.range_neighbor_repulsion == 6.0 - sim.agent(agent_id).model.range_geometry_repulsion = 7.0 - assert sim.agent(agent_id).model.range_geometry_repulsion == 7.0 + sim.agent(agent_id).model.wall_buffer_distance = 1.1 + assert sim.agent(agent_id).model.wall_buffer_distance == 1.1 - sim.agent(agent_id).model.range_geometry_repulsion = 8.0 - assert sim.agent(agent_id).model.range_geometry_repulsion == 8.0 + sim.agent(agent_id).model.anticipation_time = 2.1 + assert sim.agent(agent_id).model.anticipation_time == 2.1 + + sim.agent(agent_id).model.reaction_time = 0.31 + assert sim.agent(agent_id).model.reaction_time == 0.31 @pytest.fixture From 90920480515475967f53ddf0bbcdba71fd215bc6 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Wed, 15 Jan 2025 14:18:12 +0100 Subject: [PATCH 36/52] merge two cells in the notebook --- notebooks/model-comparison.ipynb | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/notebooks/model-comparison.ipynb b/notebooks/model-comparison.ipynb index b0a48b7b2..697be047d 100644 --- a/notebooks/model-comparison.ipynb +++ b/notebooks/model-comparison.ipynb @@ -19,7 +19,7 @@ "\n", "When it comes to computational efficiency, velocity-based models generally have an advantage. The CFM offers the fastest execution times, while the AVM provides a good balance between computational efficiency and realistic behavior simulation. Force-based models, while more computationally intensive, are necessary when accurate physical interaction modeling is crucial.\n", "\n", - "The choice of model ultimately comes down to your specific requirements. If you're simulating emergency evacuations or very crowded environments where physical interactions are important, a force-based model like GCFM would be appropriate. For typical pedestrian scenarios where smooth navigation and realistic avoidance behavior are priority, the AVM would be the better choice. In cases where computational resources are limited and physical interactions are not critical, the CFM can provide adequate results.\n", + "The choice of model ultimately comes down to your specific requirements. If you're simulating emergency evacuations or very crowded environments where physical interactions are important, a force-based model like SFM would be appropriate. For typical pedestrian scenarios where smooth navigation and realistic avoidance behavior are priority, the AVM would be the better choice. In cases where computational resources are limited and physical interactions are not critical, the CFM can provide adequate results.\n", "\n", "The key is to understand that no single model is universally superior – each has its place depending on the specific requirements of your simulation scenario.\n", "\n", @@ -63,7 +63,7 @@ { "cell_type": "code", "execution_count": null, - "id": "d47dee54-2a46-4c65-89b0-f70fe743ecfe", + "id": "b982aeaf-a056-4870-bf96-4213db17ddcd", "metadata": { "tags": [ "hide-input" @@ -78,20 +78,8 @@ "from shapely import Polygon\n", "from jupedsim.internal.notebook_utils import animate, read_sqlite_file\n", "from shapely.ops import unary_union\n", - "import pedpy" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b982aeaf-a056-4870-bf96-4213db17ddcd", - "metadata": { - "tags": [ - "hide-input" - ] - }, - "outputs": [], - "source": [ + "import pedpy\n", + "\n", "def initialize_simulation(\n", " model, agent_parameters, geometry, goals, positions, speeds, trajectory_file\n", "):\n", From bf8d45973906ef06cf9130e79d8e14ceb7fb87b5 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Wed, 15 Jan 2025 14:50:36 +0100 Subject: [PATCH 37/52] Add test default parameters of AVM --- libjupedsim/test/TestJupedsim.cpp | 26 +++++++++++++++---- .../src/AnticipationVelocityModelData.hpp | 2 +- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/libjupedsim/test/TestJupedsim.cpp b/libjupedsim/test/TestJupedsim.cpp index 60b53cb7a..e2fa10ea0 100644 --- a/libjupedsim/test/TestJupedsim.cpp +++ b/libjupedsim/test/TestJupedsim.cpp @@ -32,10 +32,23 @@ TEST(OperationalModel, CanConstructCollisionFreeSpeedModel) JPS_OperationalModel_Free(model); } +TEST(OperationalModel, DefaultsOfCollisionFreeSpeedModelAgentParameters) +{ + JPS_CollisionFreeSpeedModelAgentParameters agentParameters{}; + + ASSERT_DOUBLE_EQ(agentParameters.position.x, 0); + ASSERT_DOUBLE_EQ(agentParameters.position.y, 0); + ASSERT_DOUBLE_EQ(agentParameters.journeyId, 0); + ASSERT_DOUBLE_EQ(agentParameters.stageId, 0); + ASSERT_DOUBLE_EQ(agentParameters.time_gap, 1); + ASSERT_DOUBLE_EQ(agentParameters.v0, 1.2); + ASSERT_DOUBLE_EQ(agentParameters.radius, 0.2); +} + TEST(OperationalModel, CanConstructAnticipationVelocityModel) { JPS_ErrorMessage errorMsg{}; - auto builder = JPS_AnticipationVelocityModelBuilder_Create(1, 1, 1, 1); + auto builder = JPS_AnticipationVelocityModelBuilder_Create(); auto model = JPS_AnticipationVelocityModelBuilder_Build(builder, &errorMsg); EXPECT_NE(model, nullptr); EXPECT_EQ(errorMsg, nullptr); @@ -43,17 +56,20 @@ TEST(OperationalModel, CanConstructAnticipationVelocityModel) JPS_OperationalModel_Free(model); } -TEST(OperationalModel, DefaultsOfCollisionFreeSpeedModelAgentParameters) +TEST(OperationalModel, DefaultsOfAnticipationVelocityModelAgentParameters) { - JPS_CollisionFreeSpeedModelAgentParameters agentParameters{}; + JPS_AnticipationVelocityModelAgentParameters agentParameters{}; ASSERT_DOUBLE_EQ(agentParameters.position.x, 0); ASSERT_DOUBLE_EQ(agentParameters.position.y, 0); ASSERT_DOUBLE_EQ(agentParameters.journeyId, 0); ASSERT_DOUBLE_EQ(agentParameters.stageId, 0); - ASSERT_DOUBLE_EQ(agentParameters.time_gap, 1); + ASSERT_DOUBLE_EQ(agentParameters.time_gap, 1.06); ASSERT_DOUBLE_EQ(agentParameters.v0, 1.2); - ASSERT_DOUBLE_EQ(agentParameters.radius, 0.2); + ASSERT_DOUBLE_EQ(agentParameters.radius, 0.15); + ASSERT_DOUBLE_EQ(agentParameters.anticipationTime, 1.0); + ASSERT_DOUBLE_EQ(agentParameters.reactionTime, 0.3); + ASSERT_DOUBLE_EQ(agentParameters.wallBufferDistance, 0.1); } TEST(OperationalModel, CanConstructGeneralizedCentrifugalForceModel) diff --git a/libsimulator/src/AnticipationVelocityModelData.hpp b/libsimulator/src/AnticipationVelocityModelData.hpp index 8597aa8d5..e55438269 100644 --- a/libsimulator/src/AnticipationVelocityModelData.hpp +++ b/libsimulator/src/AnticipationVelocityModelData.hpp @@ -7,7 +7,7 @@ struct AnticipationVelocityModelData { double strengthNeighborRepulsion{}; double rangeNeighborRepulsion{}; - double wallBufferDistance{}; // buff distance of agent to wall + double wallBufferDistance{0.1}; // buff distance of agent to wall double anticipationTime{1.0}; // anticipation time double reactionTime{0.3}; // reaction time to update direction Point velocity{}; From 0b9352f6fc34ffa2ce84b4a979f95afe4f9a9b6c Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Wed, 15 Jan 2025 15:14:27 +0100 Subject: [PATCH 38/52] update AVM default parameters --- .../include/jupedsim/anticipation_velocity_model.h | 8 ++++---- libjupedsim/test/TestJupedsim.cpp | 4 ++-- libsimulator/src/AnticipationVelocityModelData.hpp | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libjupedsim/include/jupedsim/anticipation_velocity_model.h b/libjupedsim/include/jupedsim/anticipation_velocity_model.h index 5089f6f44..778bb0eea 100644 --- a/libjupedsim/include/jupedsim/anticipation_velocity_model.h +++ b/libjupedsim/include/jupedsim/anticipation_velocity_model.h @@ -217,7 +217,7 @@ typedef struct JPS_AnticipationVelocityModelAgentParameters { /** * @param time_gap of the agents using this profile (T in the OV-function) */ - double time_gap = 1.; + double time_gap = 1.06; /** * @param v0 of the agents using this profile(desired speed) double radius; */ @@ -225,7 +225,7 @@ typedef struct JPS_AnticipationVelocityModelAgentParameters { /** * @param radius of the agent in 'meters' */ - double radius = 0.2; + double radius = 0.15; /** * Strength of the repulsion from neighbors @@ -245,12 +245,12 @@ typedef struct JPS_AnticipationVelocityModelAgentParameters { /** * Anticipation time in seconds */ - double anticipationTime{1.0}; + double anticipationTime{0.5}; /** * Reaction time in seconds */ - double reactionTime{0.3}; + double reactionTime{0.1}; } JPS_AnticipationVelocityModelAgentParameters; diff --git a/libjupedsim/test/TestJupedsim.cpp b/libjupedsim/test/TestJupedsim.cpp index e2fa10ea0..3e9a913ad 100644 --- a/libjupedsim/test/TestJupedsim.cpp +++ b/libjupedsim/test/TestJupedsim.cpp @@ -67,8 +67,8 @@ TEST(OperationalModel, DefaultsOfAnticipationVelocityModelAgentParameters) ASSERT_DOUBLE_EQ(agentParameters.time_gap, 1.06); ASSERT_DOUBLE_EQ(agentParameters.v0, 1.2); ASSERT_DOUBLE_EQ(agentParameters.radius, 0.15); - ASSERT_DOUBLE_EQ(agentParameters.anticipationTime, 1.0); - ASSERT_DOUBLE_EQ(agentParameters.reactionTime, 0.3); + ASSERT_DOUBLE_EQ(agentParameters.anticipationTime, 0.5); + ASSERT_DOUBLE_EQ(agentParameters.reactionTime, 0.1); ASSERT_DOUBLE_EQ(agentParameters.wallBufferDistance, 0.1); } diff --git a/libsimulator/src/AnticipationVelocityModelData.hpp b/libsimulator/src/AnticipationVelocityModelData.hpp index e55438269..49e9539b7 100644 --- a/libsimulator/src/AnticipationVelocityModelData.hpp +++ b/libsimulator/src/AnticipationVelocityModelData.hpp @@ -8,8 +8,8 @@ struct AnticipationVelocityModelData { double strengthNeighborRepulsion{}; double rangeNeighborRepulsion{}; double wallBufferDistance{0.1}; // buff distance of agent to wall - double anticipationTime{1.0}; // anticipation time - double reactionTime{0.3}; // reaction time to update direction + double anticipationTime{0.5}; // anticipation time + double reactionTime{0.1}; // reaction time to update direction Point velocity{}; double timeGap{1.06}; double v0{1.2}; From 5e124cf738699965586d6c938a8c11f88ae8c4aa Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Wed, 15 Jan 2025 18:37:14 +0100 Subject: [PATCH 39/52] update clang format --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e821aff74..976168d6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,7 +224,7 @@ add_subdirectory(python_bindings_jupedsim) # Code formatting ################################################################################ if(UNIX AND WITH_FORMAT) - set(clang-format-version 15) + set(clang-format-version 18) find_program(CLANG_FORMAT NAMES clang-format-${clang-format-version} From 264c09b81cdb45c11b0278fe84abdeade44a6939 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Wed, 15 Jan 2025 18:45:45 +0100 Subject: [PATCH 40/52] clang-format my code --- .../src/AnticipationVelocityModel.cpp | 125 +++++++++--------- 1 file changed, 61 insertions(+), 64 deletions(-) diff --git a/libsimulator/src/AnticipationVelocityModel.cpp b/libsimulator/src/AnticipationVelocityModel.cpp index 10548c815..23f426123 100644 --- a/libsimulator/src/AnticipationVelocityModel.cpp +++ b/libsimulator/src/AnticipationVelocityModel.cpp @@ -1,23 +1,23 @@ // Copyright © 2012-2024 Forschungszentrum Jülich GmbH // SPDX-License-Identifier: LGPL-3.0-or-later #include "AnticipationVelocityModel.hpp" -#include #include "AnticipationVelocityModelData.hpp" #include "AnticipationVelocityModelUpdate.hpp" #include "GenericAgent.hpp" #include "GeometricFunctions.hpp" +#include "Macros.hpp" #include "OperationalModel.hpp" #include "SimulationError.hpp" -#include "Macros.hpp" #include #include #include #include +#include #include OperationalModelType AnticipationVelocityModel::Type() const { - return OperationalModelType::ANTICIPATION_VELOCITY_MODEL; + return OperationalModelType::ANTICIPATION_VELOCITY_MODEL; } OperationalModelUpdate AnticipationVelocityModel::ComputeNewPosition( @@ -70,12 +70,7 @@ OperationalModelUpdate AnticipationVelocityModel::ComputeNewPosition( const auto& model = std::get(ped.model); const double wallBufferDistance = model.wallBufferDistance; // Wall sliding behavior - direction = HandleWallAvoidance( - direction, - ped.pos, - model.radius, - boundary, - wallBufferDistance); + direction = HandleWallAvoidance(direction, ped.pos, model.radius, boundary, wallBufferDistance); // update direction towards the newly calculated direction direction = UpdateDirection(ped, direction, dT); @@ -103,28 +98,30 @@ void AnticipationVelocityModel::ApplyUpdate(const OperationalModelUpdate& upd, G model.velocity = update.velocity; } -Point AnticipationVelocityModel::UpdateDirection(const GenericAgent& ped, const Point & calculatedDirection, double dt -) const{ - const auto& model = std::get(ped.model); - const Point desiredDirection = (ped.destination - ped.pos).Normalized(); - Point actualDirection = ped.orientation; - Point updatedDirection; - - if(desiredDirection.ScalarProduct(calculatedDirection)*desiredDirection.ScalarProduct(actualDirection) < 0) { - updatedDirection = calculatedDirection; - } - else{ - // Compute the rate of change of direction (Eq. 7) - const Point directionDerivative = - (calculatedDirection.Normalized() - actualDirection) / model.reactionTime; - updatedDirection = actualDirection + directionDerivative * dt; -} - +Point AnticipationVelocityModel::UpdateDirection( + const GenericAgent& ped, + const Point& calculatedDirection, + double dt) const +{ + const auto& model = std::get(ped.model); + const Point desiredDirection = (ped.destination - ped.pos).Normalized(); + Point actualDirection = ped.orientation; + Point updatedDirection; + + if(desiredDirection.ScalarProduct(calculatedDirection) * + desiredDirection.ScalarProduct(actualDirection) < + 0) { + updatedDirection = calculatedDirection; + } else { + // Compute the rate of change of direction (Eq. 7) + const Point directionDerivative = + (calculatedDirection.Normalized() - actualDirection) / model.reactionTime; + updatedDirection = actualDirection + directionDerivative * dt; + } - return updatedDirection.Normalized(); + return updatedDirection.Normalized(); } - void AnticipationVelocityModel::CheckModelConstraint( const GenericAgent& agent, const NeighborhoodSearchType& neighborhoodSearch, @@ -141,13 +138,11 @@ void AnticipationVelocityModel::CheckModelConstraint( constexpr double snMax = 20.; validateConstraint(strengthNeighborRepulsion, snMin, snMax, "strengthNeighborRepulsion", false); - const auto rangeNeighborRepulsion = model.rangeNeighborRepulsion; constexpr double rnMin = 0.; constexpr double rnMax = 5.; validateConstraint(rangeNeighborRepulsion, rnMin, rnMax, "rangeNeighborRepulsion", true); - const auto buff = model.wallBufferDistance; constexpr double buffMin = 0.; constexpr double buffMax = 1.; @@ -166,14 +161,14 @@ void AnticipationVelocityModel::CheckModelConstraint( const auto anticipationTime = model.anticipationTime; constexpr double anticipationTimeMin = 0.0; constexpr double anticipationTimeMax = 5.0; - validateConstraint(anticipationTime, anticipationTimeMin, anticipationTimeMax, "anticipationTime"); + validateConstraint( + anticipationTime, anticipationTimeMin, anticipationTimeMax, "anticipationTime"); const auto reactionTime = model.reactionTime; constexpr double reactionTimeMin = 0.0; constexpr double reactionTimeMax = 1.0; validateConstraint(reactionTime, reactionTimeMin, reactionTimeMax, "reactionTime", true); - const auto neighbors = neighborhoodSearch.GetNeighboringAgents(agent.pos, 2); for(const auto& neighbor : neighbors) { if(agent.id == neighbor.id) { @@ -213,8 +208,7 @@ double AnticipationVelocityModel::OptimalSpeed( { const auto& model = std::get(ped.model); double min_spacing = 0.0; - return std::min(std::max(spacing / time_gap, min_spacing - ), model.v0); + return std::min(std::max(spacing / time_gap, min_spacing), model.v0); } double AnticipationVelocityModel::GetSpacing( @@ -239,24 +233,26 @@ double AnticipationVelocityModel::GetSpacing( return distp12.Norm() - l; } -Point AnticipationVelocityModel::CalculateInfluenceDirection(const Point& desiredDirection, const Point& predictedDirection) const +Point AnticipationVelocityModel::CalculateInfluenceDirection( + const Point& desiredDirection, + const Point& predictedDirection) const { - // Eq. (5) - static std::mt19937 gen(42); - static std::uniform_int_distribution dist(0, 1); // Random integers: 0 or 1 - - Point orthogonalDirection = Point(-desiredDirection.y, desiredDirection.x).Normalized(); - double alignment = orthogonalDirection.ScalarProduct(predictedDirection); - Point influenceDirection = orthogonalDirection; - if (fabs(alignment) < J_EPS) { - // Choose a random direction (left or right) - if (dist(gen) == 0) { - influenceDirection = -orthogonalDirection; + // Eq. (5) + static std::mt19937 gen(42); + static std::uniform_int_distribution dist(0, 1); // Random integers: 0 or 1 + + Point orthogonalDirection = Point(-desiredDirection.y, desiredDirection.x).Normalized(); + double alignment = orthogonalDirection.ScalarProduct(predictedDirection); + Point influenceDirection = orthogonalDirection; + if(fabs(alignment) < J_EPS) { + // Choose a random direction (left or right) + if(dist(gen) == 0) { + influenceDirection = -orthogonalDirection; + } + } else if(alignment > 0) { + influenceDirection = -orthogonalDirection; } - } else if (alignment > 0) { - influenceDirection = -orthogonalDirection; - } - return influenceDirection; + return influenceDirection; } Point AnticipationVelocityModel::NeighborRepulsion( @@ -269,17 +265,19 @@ Point AnticipationVelocityModel::NeighborRepulsion( const auto distp12 = ped2.pos - ped1.pos; const auto [distance, ep12] = distp12.NormAndNormalized(); const double adjustedDist = distance - (model1.radius + model2.radius); - + // Pedestrian movement and desired directions const auto& e1 = ped1.orientation; const auto& d1 = (ped1.destination - ped1.pos).Normalized(); const auto& e2 = ped2.orientation; - + // Check perception range (Eq. 1) - const auto inPerceptionRange = d1.ScalarProduct(ep12) >= 0 || e1.ScalarProduct(ep12) >= 0; - if(!inPerceptionRange) return Point(0, 0); + const auto inPerceptionRange = d1.ScalarProduct(ep12) >= 0 || e1.ScalarProduct(ep12) >= 0; + if(!inPerceptionRange) + return Point(0, 0); - double S_Gap = (model1.velocity - model2.velocity).ScalarProduct(ep12) * model1.anticipationTime; + double S_Gap = + (model1.velocity - model2.velocity).ScalarProduct(ep12) * model1.anticipationTime; double R_dist = adjustedDist - S_Gap; R_dist = std::max(R_dist, 0.0); // Clamp to zero if negative @@ -287,16 +285,15 @@ Point AnticipationVelocityModel::NeighborRepulsion( constexpr double alignmentBase = 1.0; constexpr double alignmentWeight = 0.5; const double alignmentFactor = alignmentBase + alignmentWeight * (1.0 - d1.ScalarProduct(e2)); - const double interactionStrength = model1.strengthNeighborRepulsion * alignmentFactor * std::exp(-R_dist/model1.rangeNeighborRepulsion); - auto newep12 = distp12 + model2.velocity*model2.anticipationTime ; //e_ij(t+ta) + const double interactionStrength = model1.strengthNeighborRepulsion * alignmentFactor * + std::exp(-R_dist / model1.rangeNeighborRepulsion); + auto newep12 = distp12 + model2.velocity * model2.anticipationTime; // e_ij(t+ta) // Compute adjusted influence direction const auto influenceDirection = CalculateInfluenceDirection(d1, newep12); return influenceDirection * interactionStrength; - } - Point AnticipationVelocityModel::HandleWallAvoidance( const Point& direction, const Point& agentPosition, @@ -307,9 +304,7 @@ Point AnticipationVelocityModel::HandleWallAvoidance( const double criticalWallDistance = wallBufferDistance + agentRadius; auto nearestWallIt = std::min_element( - boundary.cbegin(), - boundary.cend(), - [&agentPosition](const auto& wall1, const auto& wall2) { + boundary.cbegin(), boundary.cend(), [&agentPosition](const auto& wall1, const auto& wall2) { const auto distanceVector1 = agentPosition - wall1.ShortestPoint(agentPosition); const auto distanceVector2 = agentPosition - wall2.ShortestPoint(agentPosition); return distanceVector1.Norm() < distanceVector2.Norm(); @@ -318,7 +313,8 @@ Point AnticipationVelocityModel::HandleWallAvoidance( if(nearestWallIt != boundary.end()) { const auto closestPoint = nearestWallIt->ShortestPoint(agentPosition); const auto distanceVector = agentPosition - closestPoint; - auto [perpendicularDistance, directionAwayFromBoundary] = distanceVector.NormAndNormalized(); + auto [perpendicularDistance, directionAwayFromBoundary] = + distanceVector.NormAndNormalized(); if(perpendicularDistance < criticalWallDistance) { // Agent is too close to wall @@ -328,7 +324,8 @@ Point AnticipationVelocityModel::HandleWallAvoidance( const auto wallVector = nearestWallIt->p2 - nearestWallIt->p1; const auto wallDirection = wallVector.Normalized(); // Project direction onto wall - const auto parallelComponent = wallDirection * direction.ScalarProduct(wallDirection); + const auto parallelComponent = + wallDirection * direction.ScalarProduct(wallDirection); return parallelComponent.Normalized(); } } From 42da8e28d45d9d8d5ba896fc0605b82a59042f17 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Wed, 15 Jan 2025 18:48:06 +0100 Subject: [PATCH 41/52] clangformating --- libsimulator/src/AnticipationVelocityModel.hpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libsimulator/src/AnticipationVelocityModel.hpp b/libsimulator/src/AnticipationVelocityModel.hpp index 5a02ae149..c4a360a5e 100644 --- a/libsimulator/src/AnticipationVelocityModel.hpp +++ b/libsimulator/src/AnticipationVelocityModel.hpp @@ -33,9 +33,10 @@ class AnticipationVelocityModel : public OperationalModel std::unique_ptr Clone() const override; private: - double OptimalSpeed(const GenericAgent& ped, double spacing, double time_gap) - const; - Point CalculateInfluenceDirection(const Point& desiredDirection, const Point& predictedDirection) const; + double OptimalSpeed(const GenericAgent& ped, double spacing, double time_gap) const; + Point CalculateInfluenceDirection( + const Point& desiredDirection, + const Point& predictedDirection) const; double GetSpacing(const GenericAgent& ped1, const GenericAgent& ped2, const Point& direction) const; Point NeighborRepulsion(const GenericAgent& ped1, const GenericAgent& ped2) const; @@ -47,6 +48,6 @@ class AnticipationVelocityModel : public OperationalModel const std::vector& boundary, double wallBufferDistance) const; - Point UpdateDirection(const GenericAgent& ped, const Point& calculatedDirection, double dt) const; - + Point + UpdateDirection(const GenericAgent& ped, const Point& calculatedDirection, double dt) const; }; From c615170108a38eef3e9762a691e3f22f62f035c8 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Wed, 15 Jan 2025 18:52:07 +0100 Subject: [PATCH 42/52] clang-formating a bunch --- libjupedsim/include/jupedsim/agent.h | 3 +- libjupedsim/include/jupedsim/simulation.h | 3 +- libjupedsim/src/agent.cpp | 2 +- .../src/anticipation_velocity_model.cpp | 36 +++++++++---------- libsimulator/src/GenericAgent.hpp | 2 +- libsimulator/src/Mesh.cpp | 4 +-- 6 files changed, 22 insertions(+), 28 deletions(-) diff --git a/libjupedsim/include/jupedsim/agent.h b/libjupedsim/include/jupedsim/agent.h index ff1e683d7..daf30ffb2 100644 --- a/libjupedsim/include/jupedsim/agent.h +++ b/libjupedsim/include/jupedsim/agent.h @@ -2,9 +2,9 @@ /* SPDX-License-Identifier: LGPL-3.0-or-later */ #pragma once +#include "anticipation_velocity_model.h" #include "collision_free_speed_model.h" #include "collision_free_speed_model_v2.h" -#include "anticipation_velocity_model.h" #include "error.h" #include "export.h" #include "generalized_centrifugal_force_model.h" @@ -127,7 +127,6 @@ JPS_Agent_GetCollisionFreeSpeedModelV2State(JPS_Agent handle, JPS_ErrorMessage* JUPEDSIM_API JPS_AnticipationVelocityModelState JPS_Agent_GetAnticipationVelocityModelState(JPS_Agent handle, JPS_ErrorMessage* errorMessage); - /** * Opaque type of an iterator over agents */ diff --git a/libjupedsim/include/jupedsim/simulation.h b/libjupedsim/include/jupedsim/simulation.h index 8d412de6a..c5f12545f 100644 --- a/libjupedsim/include/jupedsim/simulation.h +++ b/libjupedsim/include/jupedsim/simulation.h @@ -3,9 +3,9 @@ #pragma once #include "agent.h" +#include "anticipation_velocity_model.h" #include "collision_free_speed_model.h" #include "collision_free_speed_model_v2.h" -#include "anticipation_velocity_model.h" #include "error.h" #include "export.h" #include "generalized_centrifugal_force_model.h" @@ -205,7 +205,6 @@ JUPEDSIM_API JPS_AgentId JPS_Simulation_AddAnticipationVelocityModelAgent( JPS_AnticipationVelocityModelAgentParameters parameters, JPS_ErrorMessage* errorMessage); - /** * Adds a new agent to the simulation. * This can be called at any time, i.e. agents can be added at any iteration. diff --git a/libjupedsim/src/agent.cpp b/libjupedsim/src/agent.cpp index 7238d0606..2512a75a0 100644 --- a/libjupedsim/src/agent.cpp +++ b/libjupedsim/src/agent.cpp @@ -91,7 +91,7 @@ JPS_ModelType JPS_Agent_GetModelType(JPS_Agent handle) case 2: return JPS_CollisionFreeSpeedModelV2; case 3: - return JPS_AnticipationVelocityModel; + return JPS_AnticipationVelocityModel; case 4: return JPS_SocialForceModel; } diff --git a/libjupedsim/src/anticipation_velocity_model.cpp b/libjupedsim/src/anticipation_velocity_model.cpp index 860415301..707a128e0 100644 --- a/libjupedsim/src/anticipation_velocity_model.cpp +++ b/libjupedsim/src/anticipation_velocity_model.cpp @@ -89,49 +89,47 @@ void JPS_AnticipationVelocityModelState_SetRangeNeighborRepulsion( state->rangeNeighborRepulsion = rangeNeighborRepulsion; } -double JPS_AnticipationVelocityModelState_GetAnticipationTime( -JPS_AnticipationVelocityModelState handle) +double +JPS_AnticipationVelocityModelState_GetAnticipationTime(JPS_AnticipationVelocityModelState handle) { - assert(handle); - const auto state = reinterpret_cast(handle); - return state->anticipationTime; + assert(handle); + const auto state = reinterpret_cast(handle); + return state->anticipationTime; } void JPS_AnticipationVelocityModelState_SetAnticipationTime( JPS_AnticipationVelocityModelState handle, double anticipationTime) { - assert(handle); - auto state = reinterpret_cast(handle); - state->anticipationTime = anticipationTime; + assert(handle); + auto state = reinterpret_cast(handle); + state->anticipationTime = anticipationTime; } -double JPS_AnticipationVelocityModelState_GetReactionTime( -JPS_AnticipationVelocityModelState handle) +double JPS_AnticipationVelocityModelState_GetReactionTime(JPS_AnticipationVelocityModelState handle) { - assert(handle); - const auto state = reinterpret_cast(handle); - return state->reactionTime; + assert(handle); + const auto state = reinterpret_cast(handle); + return state->reactionTime; } void JPS_AnticipationVelocityModelState_SetReactionTime( JPS_AnticipationVelocityModelState handle, double reactionTime) { - assert(handle); - auto state = reinterpret_cast(handle); - state->reactionTime = reactionTime; + assert(handle); + auto state = reinterpret_cast(handle); + state->reactionTime = reactionTime; } -double JPS_AnticipationVelocityModelState_GetWallBufferDistance( - JPS_AnticipationVelocityModelState handle) +double +JPS_AnticipationVelocityModelState_GetWallBufferDistance(JPS_AnticipationVelocityModelState handle) { assert(handle); const auto state = reinterpret_cast(handle); return state->wallBufferDistance; } - void JPS_AnticipationVelocityModelState_SetWallBufferDistance( JPS_AnticipationVelocityModelState handle, double wallBufferDistance) diff --git a/libsimulator/src/GenericAgent.hpp b/libsimulator/src/GenericAgent.hpp index 5857ef307..edac57cbc 100644 --- a/libsimulator/src/GenericAgent.hpp +++ b/libsimulator/src/GenericAgent.hpp @@ -1,9 +1,9 @@ // Copyright © 2012-2024 Forschungszentrum Jülich GmbH // SPDX-License-Identifier: LGPL-3.0-or-later #pragma once +#include "AnticipationVelocityModelData.hpp" #include "CollisionFreeSpeedModelData.hpp" #include "CollisionFreeSpeedModelV2Data.hpp" -#include "AnticipationVelocityModelData.hpp" #include "GeneralizedCentrifugalForceModelData.hpp" #include "OperationalModel.hpp" #include "Point.hpp" diff --git a/libsimulator/src/Mesh.cpp b/libsimulator/src/Mesh.cpp index 62fd01ff3..1f22069b2 100644 --- a/libsimulator/src/Mesh.cpp +++ b/libsimulator/src/Mesh.cpp @@ -416,9 +416,7 @@ std::vector Mesh::FVertices() const std::begin(vertices), std::end(vertices), std::back_inserter(f_vertices), - [](const auto& v) { - return glm::vec2{v.x, v.y}; - }); + [](const auto& v) { return glm::vec2{v.x, v.y}; }); return f_vertices; } From 5710c4c61b81fc365ceac876fdca38c4d96bc3f3 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Wed, 15 Jan 2025 18:53:51 +0100 Subject: [PATCH 43/52] clang formatting --- libjupedsim/include/jupedsim/jupedsim.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libjupedsim/include/jupedsim/jupedsim.h b/libjupedsim/include/jupedsim/jupedsim.h index 18bf59787..44120750f 100644 --- a/libjupedsim/include/jupedsim/jupedsim.h +++ b/libjupedsim/include/jupedsim/jupedsim.h @@ -3,10 +3,10 @@ #pragma once #include "agent.h" +#include "anticipation_velocity_model.h" #include "build_info.h" #include "collision_free_speed_model.h" #include "collision_free_speed_model_v2.h" -#include "anticipation_velocity_model.h" #include "error.h" #include "export.h" #include "generalized_centrifugal_force_model.h" From e339d7190666a20356c3db8dbe80032b91d7f87e Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Wed, 15 Jan 2025 19:10:41 +0100 Subject: [PATCH 44/52] sorting imports and ruffing --- CMakeLists.txt | 2 +- examples/example7_avm.py | 1 - examples/example8_headon_AVM.py | 3 --- examples/example8_headon_CSM.py | 1 + notebooks/model-comparison.ipynb | 11 ++++++----- python_modules/jupedsim/jupedsim/__init__.py | 11 +++++------ python_modules/jupedsim/jupedsim/agent.py | 6 +++--- python_modules/jupedsim/jupedsim/simulation.py | 8 ++++---- 8 files changed, 20 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 976168d6e..309c3599c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,7 +224,7 @@ add_subdirectory(python_bindings_jupedsim) # Code formatting ################################################################################ if(UNIX AND WITH_FORMAT) - set(clang-format-version 18) + set(clang-format-version 19) find_program(CLANG_FORMAT NAMES clang-format-${clang-format-version} diff --git a/examples/example7_avm.py b/examples/example7_avm.py index 06a46fa1d..aa850350f 100644 --- a/examples/example7_avm.py +++ b/examples/example7_avm.py @@ -7,7 +7,6 @@ import sys import jupedsim as jps -import shapely from shapely import Polygon diff --git a/examples/example8_headon_AVM.py b/examples/example8_headon_AVM.py index 11750d638..8b4f9055f 100644 --- a/examples/example8_headon_AVM.py +++ b/examples/example8_headon_AVM.py @@ -4,10 +4,8 @@ # SPDX-License-Identifier: LGPL-3.0-or-later import pathlib -import sys import jupedsim as jps -import shapely from shapely import Polygon @@ -15,7 +13,6 @@ def main(): width = 2 length = 10 geometry = Polygon([(0, 0), (length, 0), (length, width), (0, width)]) - num_agents = 2 exit_polygon = Polygon( [(length - 0.5, 0), (length, 0), (length, width), (length - 0.5, width)] ) diff --git a/examples/example8_headon_CSM.py b/examples/example8_headon_CSM.py index 42ce6922d..30a2c5faf 100644 --- a/examples/example8_headon_CSM.py +++ b/examples/example8_headon_CSM.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: LGPL-3.0-or-later import pathlib + import jupedsim as jps from shapely import Polygon diff --git a/notebooks/model-comparison.ipynb b/notebooks/model-comparison.ipynb index 697be047d..5f47691a6 100644 --- a/notebooks/model-comparison.ipynb +++ b/notebooks/model-comparison.ipynb @@ -72,18 +72,18 @@ "outputs": [], "source": [ "import pathlib\n", + "\n", "import jupedsim as jps\n", "import matplotlib.pyplot as plt\n", "import pedpy\n", - "from shapely import Polygon\n", "from jupedsim.internal.notebook_utils import animate, read_sqlite_file\n", + "from shapely import Polygon\n", "from shapely.ops import unary_union\n", - "import pedpy\n", + "\n", "\n", "def initialize_simulation(\n", " model, agent_parameters, geometry, goals, positions, speeds, trajectory_file\n", "):\n", - "\n", " simulation = jps.Simulation(\n", " model=model,\n", " geometry=geometry,\n", @@ -179,8 +179,9 @@ " print(f\"Evacuation time: {simulation.elapsed_time():.2f} s\")\n", " return simulation.elapsed_time()\n", "\n", - "width=600\n", - "height=600" + "\n", + "width = 600\n", + "height = 600" ] }, { diff --git a/python_modules/jupedsim/jupedsim/__init__.py b/python_modules/jupedsim/jupedsim/__init__.py index e607badef..1cc13298f 100644 --- a/python_modules/jupedsim/jupedsim/__init__.py +++ b/python_modules/jupedsim/jupedsim/__init__.py @@ -25,6 +25,11 @@ set_info_callback, set_warning_callback, ) +from jupedsim.models.anticipation_velocity_model import ( + AnticipationVelocityModel, + AnticipationVelocityModelAgentParameters, + AnticipationVelocityModelState, +) from jupedsim.models.collision_free_speed import ( CollisionFreeSpeedModel, CollisionFreeSpeedModelAgentParameters, @@ -35,12 +40,6 @@ CollisionFreeSpeedModelV2AgentParameters, CollisionFreeSpeedModelV2State, ) -from jupedsim.models.anticipation_velocity_model import ( - AnticipationVelocityModel, - AnticipationVelocityModelAgentParameters, - AnticipationVelocityModelState, -) - from jupedsim.models.generalized_centrifugal_force import ( GeneralizedCentrifugalForceModel, GeneralizedCentrifugalForceModelAgentParameters, diff --git a/python_modules/jupedsim/jupedsim/agent.py b/python_modules/jupedsim/jupedsim/agent.py index d35f1ad01..00096970b 100644 --- a/python_modules/jupedsim/jupedsim/agent.py +++ b/python_modules/jupedsim/jupedsim/agent.py @@ -2,13 +2,13 @@ # SPDX-License-Identifier: LGPL-3.0-or-later import jupedsim.native as py_jps +from jupedsim.models.anticipation_velocity_model import ( + AnticipationVelocityModelState, +) from jupedsim.models.collision_free_speed import CollisionFreeSpeedModelState from jupedsim.models.collision_free_speed_v2 import ( CollisionFreeSpeedModelV2State, ) -from jupedsim.models.anticipation_velocity_model import ( - AnticipationVelocityModelState, -) from jupedsim.models.generalized_centrifugal_force import ( GeneralizedCentrifugalForceModelState, ) diff --git a/python_modules/jupedsim/jupedsim/simulation.py b/python_modules/jupedsim/jupedsim/simulation.py index b401d28e0..cc9acab2c 100644 --- a/python_modules/jupedsim/jupedsim/simulation.py +++ b/python_modules/jupedsim/jupedsim/simulation.py @@ -11,6 +11,10 @@ from jupedsim.geometry_utils import build_geometry from jupedsim.internal.tracing import Trace from jupedsim.journey import JourneyDescription +from jupedsim.models.anticipation_velocity_model import ( + AnticipationVelocityModel, + AnticipationVelocityModelAgentParameters, +) from jupedsim.models.collision_free_speed import ( CollisionFreeSpeedModel, CollisionFreeSpeedModelAgentParameters, @@ -19,10 +23,6 @@ CollisionFreeSpeedModelV2, CollisionFreeSpeedModelV2AgentParameters, ) -from jupedsim.models.anticipation_velocity_model import ( - AnticipationVelocityModel, - AnticipationVelocityModelAgentParameters, -) from jupedsim.models.generalized_centrifugal_force import ( GeneralizedCentrifugalForceModel, GeneralizedCentrifugalForceModelAgentParameters, From 0045715eab57263c9d1a46b97e892b1faf9251ca Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Wed, 15 Jan 2025 19:13:28 +0100 Subject: [PATCH 45/52] use clang-format 18 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 309c3599c..976168d6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,7 +224,7 @@ add_subdirectory(python_bindings_jupedsim) # Code formatting ################################################################################ if(UNIX AND WITH_FORMAT) - set(clang-format-version 19) + set(clang-format-version 18) find_program(CLANG_FORMAT NAMES clang-format-${clang-format-version} From 7db6421d755b887c3745f428139c5faf20bcc66a Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Wed, 15 Jan 2025 19:56:15 +0100 Subject: [PATCH 46/52] clang format --- libsimulator/src/Journey.hpp | 2 +- libsimulator/src/NeighborhoodSearch.hpp | 2 +- libsimulator/src/Point.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libsimulator/src/Journey.hpp b/libsimulator/src/Journey.hpp index 8c51a99ca..287fcf0f7 100644 --- a/libsimulator/src/Journey.hpp +++ b/libsimulator/src/Journey.hpp @@ -96,7 +96,7 @@ class FixedTransition : public Transition BaseStage* next; public: - FixedTransition(BaseStage* next_) : next(next_){}; + FixedTransition(BaseStage* next_) : next(next_) {}; BaseStage* NextStage() override { return next; } }; diff --git a/libsimulator/src/NeighborhoodSearch.hpp b/libsimulator/src/NeighborhoodSearch.hpp index 712a87965..da589910a 100644 --- a/libsimulator/src/NeighborhoodSearch.hpp +++ b/libsimulator/src/NeighborhoodSearch.hpp @@ -73,7 +73,7 @@ class NeighborhoodSearch } public: - explicit NeighborhoodSearch(double cellSize) : _cellSize(cellSize){}; + explicit NeighborhoodSearch(double cellSize) : _cellSize(cellSize) {}; void AddAgent(const Value& item) { diff --git a/libsimulator/src/Point.hpp b/libsimulator/src/Point.hpp index b0a1d112c..1a411184c 100644 --- a/libsimulator/src/Point.hpp +++ b/libsimulator/src/Point.hpp @@ -15,7 +15,7 @@ class Point double y{}; public: - Point(double x = 0, double y = 0) : x(x), y(y){}; + Point(double x = 0, double y = 0) : x(x), y(y) {}; /// Norm double Norm() const; From 35da307f077eef8681fea41b3cd837ec9f17bfb2 Mon Sep 17 00:00:00 2001 From: Ozaq Date: Wed, 15 Jan 2025 20:03:06 +0100 Subject: [PATCH 47/52] Fixed python formatting --- notebooks/direct_steering.ipynb | 2 +- notebooks/journey.ipynb | 2 +- notebooks/lane-formation.ipynb | 12 +-- notebooks/model-comparison.ipynb | 147 +++++++++++++++++++++++++++---- notebooks/routing.ipynb | 2 +- 5 files changed, 139 insertions(+), 26 deletions(-) diff --git a/notebooks/direct_steering.ipynb b/notebooks/direct_steering.ipynb index 19b02eefc..9bc7be267 100644 --- a/notebooks/direct_steering.ipynb +++ b/notebooks/direct_steering.ipynb @@ -132,7 +132,7 @@ " for idx, waypoint in enumerate(waypoints):\n", " axes.plot(waypoint[0], waypoint[1], \"ro\")\n", " axes.annotate(\n", - " f\"WP {idx+1}\",\n", + " f\"WP {idx + 1}\",\n", " (waypoint[0], waypoint[1]),\n", " textcoords=\"offset points\",\n", " xytext=(10, -15),\n", diff --git a/notebooks/journey.ipynb b/notebooks/journey.ipynb index d4cbfc96e..2cb6f0314 100644 --- a/notebooks/journey.ipynb +++ b/notebooks/journey.ipynb @@ -138,7 +138,7 @@ "for idx, waypoint in enumerate(waypoints):\n", " ax.plot(waypoint[0], waypoint[1], \"ro\")\n", " ax.annotate(\n", - " f\"WP {idx+1}\",\n", + " f\"WP {idx + 1}\",\n", " (waypoint[0], waypoint[1]),\n", " textcoords=\"offset points\",\n", " xytext=(10, -15),\n", diff --git a/notebooks/lane-formation.ipynb b/notebooks/lane-formation.ipynb index 0f8a7125c..10f989b03 100644 --- a/notebooks/lane-formation.ipynb +++ b/notebooks/lane-formation.ipynb @@ -90,7 +90,7 @@ " plt.text(\n", " centroid.x,\n", " centroid.y,\n", - " f\"Start {id+1}\",\n", + " f\"Start {id + 1}\",\n", " ha=\"center\",\n", " va=\"center\",\n", " fontsize=10,\n", @@ -277,7 +277,7 @@ " every_nth_frame=5,\n", " width=1200,\n", " height=400,\n", - " title_note=f\"Ratio: {min(number)/sum(number):0.2f}\",\n", + " title_note=f\"Ratio: {min(number) / sum(number):0.2f}\",\n", " ).show()" ] }, @@ -307,7 +307,7 @@ " traj_width=0.3,\n", " traj_start_marker=\".\",\n", " )\n", - " ax.set_title(f\"Ratio: {min(number)/sum(number):.2f}\")\n", + " ax.set_title(f\"Ratio: {min(number) / sum(number):.2f}\")\n", "plt.tight_layout()\n", "fig.set_size_inches((10, 12))\n", "plt.show()" @@ -385,7 +385,7 @@ " pedpy.plot_density(\n", " density=density_voronoi[number], axes=ax0, color=colors[i]\n", " )\n", - " labels.append(f\"Ratio: {min(number)/sum(number):.3f}\")\n", + " labels.append(f\"Ratio: {min(number) / sum(number):.3f}\")\n", "\n", "ax0.legend(labels)\n", "plt.show()" @@ -474,14 +474,14 @@ " pedpy.plot_speed(\n", " speed=mean_speed_r[number],\n", " axes=ax,\n", - " title=f\"Mean speed. Ratio: {min(number)/sum(number):.3f}\",\n", + " title=f\"Mean speed. Ratio: {min(number) / sum(number):.3f}\",\n", " color=pedpy.PEDPY_BLUE,\n", " )\n", "\n", " if number in mean_speed_l:\n", " pedpy.plot_speed(\n", " speed=mean_speed_l[number],\n", - " title=f\"Mean speed. Ratio: {min(number)/sum(number):.3f}\",\n", + " title=f\"Mean speed. Ratio: {min(number) / sum(number):.3f}\",\n", " axes=ax,\n", " color=pedpy.PEDPY_RED,\n", " )\n", diff --git a/notebooks/model-comparison.ipynb b/notebooks/model-comparison.ipynb index 5f47691a6..023c2d141 100644 --- a/notebooks/model-comparison.ipynb +++ b/notebooks/model-comparison.ipynb @@ -173,7 +173,8 @@ "\n", "def run_simulation(simulation, max_iterations=4000):\n", " while (\n", - " simulation.agent_count() > 0 and simulation.iteration_count() < max_iterations\n", + " simulation.agent_count() > 0\n", + " and simulation.iteration_count() < max_iterations\n", " ):\n", " simulation.iterate()\n", " print(f\"Evacuation time: {simulation.elapsed_time():.2f} s\")\n", @@ -275,7 +276,14 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=5000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" + "animate(\n", + " trajectories,\n", + " walkable_area,\n", + " title_note=model,\n", + " every_nth_frame=5,\n", + " width=width,\n", + " height=height,\n", + ")" ] }, { @@ -306,7 +314,14 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=5000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" + "animate(\n", + " trajectories,\n", + " walkable_area,\n", + " title_note=model,\n", + " every_nth_frame=5,\n", + " width=width,\n", + " height=height,\n", + ")" ] }, { @@ -337,7 +352,14 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=5000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" + "animate(\n", + " trajectories,\n", + " walkable_area,\n", + " title_note=model,\n", + " every_nth_frame=5,\n", + " width=width,\n", + " height=height,\n", + ")" ] }, { @@ -368,7 +390,14 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=5000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" + "animate(\n", + " trajectories,\n", + " walkable_area,\n", + " title_note=model,\n", + " every_nth_frame=5,\n", + " width=width,\n", + " height=height,\n", + ")" ] }, { @@ -477,7 +506,14 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" + "animate(\n", + " trajectories,\n", + " walkable_area,\n", + " title_note=model,\n", + " every_nth_frame=5,\n", + " width=width,\n", + " height=height,\n", + ")" ] }, { @@ -508,7 +544,14 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" + "animate(\n", + " trajectories,\n", + " walkable_area,\n", + " title_note=model,\n", + " every_nth_frame=5,\n", + " width=width,\n", + " height=height,\n", + ")" ] }, { @@ -539,7 +582,14 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" + "animate(\n", + " trajectories,\n", + " walkable_area,\n", + " title_note=model,\n", + " every_nth_frame=5,\n", + " width=width,\n", + " height=height,\n", + ")" ] }, { @@ -570,7 +620,14 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" + "animate(\n", + " trajectories,\n", + " walkable_area,\n", + " title_note=model,\n", + " every_nth_frame=5,\n", + " width=width,\n", + " height=height,\n", + ")" ] }, { @@ -656,7 +713,14 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" + "animate(\n", + " trajectories,\n", + " walkable_area,\n", + " title_note=model,\n", + " every_nth_frame=5,\n", + " width=width,\n", + " height=height,\n", + ")" ] }, { @@ -687,7 +751,14 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" + "animate(\n", + " trajectories,\n", + " walkable_area,\n", + " title_note=model,\n", + " every_nth_frame=5,\n", + " width=width,\n", + " height=height,\n", + ")" ] }, { @@ -718,7 +789,14 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" + "animate(\n", + " trajectories,\n", + " walkable_area,\n", + " title_note=model,\n", + " every_nth_frame=5,\n", + " width=width,\n", + " height=height,\n", + ")" ] }, { @@ -749,7 +827,14 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=5000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" + "animate(\n", + " trajectories,\n", + " walkable_area,\n", + " title_note=model,\n", + " every_nth_frame=5,\n", + " width=width,\n", + " height=height,\n", + ")" ] }, { @@ -852,7 +937,14 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" + "animate(\n", + " trajectories,\n", + " walkable_area,\n", + " title_note=model,\n", + " every_nth_frame=5,\n", + " width=width,\n", + " height=height,\n", + ")" ] }, { @@ -883,7 +975,14 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" + "animate(\n", + " trajectories,\n", + " walkable_area,\n", + " title_note=model,\n", + " every_nth_frame=5,\n", + " width=width,\n", + " height=height,\n", + ")" ] }, { @@ -914,7 +1013,14 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" + "animate(\n", + " trajectories,\n", + " walkable_area,\n", + " title_note=model,\n", + " every_nth_frame=5,\n", + " width=width,\n", + " height=height,\n", + ")" ] }, { @@ -945,7 +1051,14 @@ ")\n", "times_dict[model] = run_simulation(simulation, max_iterations=2000)\n", "trajectories, walkable_area = read_sqlite_file(trajectory_file)\n", - "animate(trajectories, walkable_area, title_note=model, every_nth_frame=5, width=width, height=height)" + "animate(\n", + " trajectories,\n", + " walkable_area,\n", + " title_note=model,\n", + " every_nth_frame=5,\n", + " width=width,\n", + " height=height,\n", + ")" ] }, { diff --git a/notebooks/routing.ipynb b/notebooks/routing.ipynb index c1d680ce2..e26db3bc5 100644 --- a/notebooks/routing.ipynb +++ b/notebooks/routing.ipynb @@ -93,7 +93,7 @@ "for idx, (waypoint, distance) in enumerate(waypoints):\n", " ax.plot(waypoint[0], waypoint[1], \"ro\")\n", " ax.annotate(\n", - " f\"WP {idx+1}\",\n", + " f\"WP {idx + 1}\",\n", " (waypoint[0], waypoint[1]),\n", " textcoords=\"offset points\",\n", " xytext=(10, -15),\n", From 9dfd0a4cd3e47f62729db8c7b724f499bb6cf3d9 Mon Sep 17 00:00:00 2001 From: Ozaq Date: Wed, 15 Jan 2025 20:14:34 +0100 Subject: [PATCH 48/52] Format cpp code to match newer clang-format version --- libsimulator/src/Journey.hpp | 2 +- libsimulator/src/NeighborhoodSearch.hpp | 2 +- libsimulator/src/Point.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libsimulator/src/Journey.hpp b/libsimulator/src/Journey.hpp index 287fcf0f7..8c51a99ca 100644 --- a/libsimulator/src/Journey.hpp +++ b/libsimulator/src/Journey.hpp @@ -96,7 +96,7 @@ class FixedTransition : public Transition BaseStage* next; public: - FixedTransition(BaseStage* next_) : next(next_) {}; + FixedTransition(BaseStage* next_) : next(next_){}; BaseStage* NextStage() override { return next; } }; diff --git a/libsimulator/src/NeighborhoodSearch.hpp b/libsimulator/src/NeighborhoodSearch.hpp index da589910a..712a87965 100644 --- a/libsimulator/src/NeighborhoodSearch.hpp +++ b/libsimulator/src/NeighborhoodSearch.hpp @@ -73,7 +73,7 @@ class NeighborhoodSearch } public: - explicit NeighborhoodSearch(double cellSize) : _cellSize(cellSize) {}; + explicit NeighborhoodSearch(double cellSize) : _cellSize(cellSize){}; void AddAgent(const Value& item) { diff --git a/libsimulator/src/Point.hpp b/libsimulator/src/Point.hpp index 1a411184c..b0a1d112c 100644 --- a/libsimulator/src/Point.hpp +++ b/libsimulator/src/Point.hpp @@ -15,7 +15,7 @@ class Point double y{}; public: - Point(double x = 0, double y = 0) : x(x), y(y) {}; + Point(double x = 0, double y = 0) : x(x), y(y){}; /// Norm double Norm() const; From 7320f23f3bce5ee19b339e5423bf3fcb155e7865 Mon Sep 17 00:00:00 2001 From: Ozaq Date: Wed, 15 Jan 2025 20:16:50 +0100 Subject: [PATCH 49/52] Fix formatting --- python_modules/jupedsim/jupedsim/internal/notebook_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python_modules/jupedsim/jupedsim/internal/notebook_utils.py b/python_modules/jupedsim/jupedsim/internal/notebook_utils.py index 00b2db41b..daab8c50e 100644 --- a/python_modules/jupedsim/jupedsim/internal/notebook_utils.py +++ b/python_modules/jupedsim/jupedsim/internal/notebook_utils.py @@ -46,7 +46,7 @@ def _speed_to_color(speed, min_speed, max_speed): """Map a speed value to a color using a colormap.""" normalized_speed = (speed - min_speed) / (max_speed - min_speed) r, g, b = plt.cm.jet_r(normalized_speed)[:3] - return f"rgba({r*255:.0f}, {g*255:.0f}, {b*255:.0f}, 0.5)" + return f"rgba({r * 255:.0f}, {g * 255:.0f}, {b * 255:.0f}, 0.5)" def _get_line_color(disk_color): From d19228b02e847491808f967c97d0ec94306285ed Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Wed, 15 Jan 2025 20:42:34 +0100 Subject: [PATCH 50/52] set version to 1.3.0 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 976168d6e..ee21d02b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ # Project setup ################################################################################ cmake_minimum_required(VERSION 3.22 FATAL_ERROR) -project(JuPedSim VERSION 1.3.1 LANGUAGES CXX) +project(JuPedSim VERSION 1.3.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) From 2444f891415a635ff2360e3efec8142be027fc51 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Wed, 15 Jan 2025 20:53:25 +0100 Subject: [PATCH 51/52] update example 7 --- examples/example7_avm.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/examples/example7_avm.py b/examples/example7_avm.py index aa850350f..78409f7f8 100644 --- a/examples/example7_avm.py +++ b/examples/example7_avm.py @@ -12,9 +12,7 @@ def main(): room1 = Polygon([(0, 0), (10, 0), (10, 10), (0, 10)]) # Room 1 (10m x 10m) - room2 = Polygon( - [(15, 0), (25, 0), (25, 10), (15, 10)] - ) # Room 2 (10m x 10m) + room2 = Polygon([(15, 0), (25, 0), (25, 10), (15, 10)]) width = 0.8 num_agents = 10 corridor = Polygon( @@ -26,8 +24,6 @@ def main(): ] ) geometry = room1.union(room2).union(corridor) - # geometry = shapely.GeometryCollection(shapely.box(0, -2.5, 50, 2.5)) - # exit_polygon = shapely.box(48, -2.5, 50, 2.5) # exit_polygon = Polygon([(24, 4.5), (25, 4.5), (25, 5.5), (24, 5.5)]) trajectory_file = "example_7.sqlite" simulation = jps.Simulation( @@ -44,7 +40,6 @@ def main(): start_positions = jps.distribute_by_number( polygon=Polygon([(0, 0), (5, 0), (5, 10), (0, 10)]), - # shapely.box(0, -2.5, 5, 2.5), number_of_agents=num_agents, distance_to_agents=0.5, distance_to_polygon=0.2, @@ -56,11 +51,8 @@ def main(): journey_id=journey_id, stage_id=exit_id, position=position, - radius=0.2, - # strength_neighbor_repulsion=8, - # range_neighbor_repulsion=0.1, - # strength_geometry_repulsion=5, - # range_geometry_repulsion=0.1, + anticipation_time=0.5, + reaction_time=0.3, ) ) From 9fbb00d00ef1593dfc81127b1bd6afce1cf24812 Mon Sep 17 00:00:00 2001 From: Mohcine Chraibi Date: Wed, 15 Jan 2025 21:10:35 +0100 Subject: [PATCH 52/52] reformatting and restructuring the comparison-models notebook --- notebooks/model-comparison.ipynb | 83 +++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 29 deletions(-) diff --git a/notebooks/model-comparison.ipynb b/notebooks/model-comparison.ipynb index 023c2d141..98fa31b14 100644 --- a/notebooks/model-comparison.ipynb +++ b/notebooks/model-comparison.ipynb @@ -2,62 +2,87 @@ "cells": [ { "cell_type": "markdown", - "id": "4b5a43f7-9248-4302-ba6e-9eb86c490be2", + "id": "d328babd", "metadata": {}, "source": [ "# Comparative Analysis of Pedestrian Dynamics Models\n", "\n", "## Objective\n", "\n", - "This notebook compares four pedestrian dynamics models by simulating agent behavior in a structured environment. Using simplified scenarios, we analyze how each model handles navigation, obstacle avoidance, and agent interactions. This comparison reveals the strengths and weaknesses of each approach, helping inform model selection when using JuPedSim.\n", + "This notebook compares four pedestrian dynamics models by simulating agent behavior in a \n", + "structured environment. Using simplified scenarios, we analyze how each model handles \n", + "navigation, obstacle avoidance, and agent interactions. This comparison reveals the strengths \n", + "and weaknesses of each approach, helping inform model selection when using JuPedSim.\n", "\n", - "When choosing a pedestrian dynamics model in JuPedSim, the decision largely depends on the specific scenario you want to simulate or the behavior you want to reproduce. The available models can be divided into two main categories: force-based and velocity-based models, each with their own strengths and limitations.\n", + "When choosing a pedestrian dynamics model in JuPedSim, the decision largely depends on the \n", + "specific scenario you want to simulate or the behavior you want to reproduce. The available \n", + "models can be divided into two main categories: **force-based** and **velocity-based** models, \n", + "each with their own strengths and limitations.\n", "\n", - "Force-based models, which include the Social Force Model (SFM) and the Generalized Centrifugal Force Model (GCFM), excel at simulating physical interactions between pedestrians. These models are particularly effective at capturing pushing behavior in dense crowds, making them ideal for evacuation scenarios or situations where physical contact between pedestrians is common. The GCFM offers some improvements over the basic SFM, particularly in handling body shape effects.\n", + "### Force-Based Models\n", "\n", - "On the other hand, velocity-based models like the Collision-Free Model (CFM) and the Anticipation Velocity Model (AVM) are better suited for normal walking situations where collision avoidance is the primary concern. These models typically produce smoother, more realistic trajectories in regular-density scenarios. The AVM, in particular, stands out for its superior collision avoidance capabilities and ability to reproduce lane formation behavior, as demonstrated in [recent research](https://doi.org/10.1016/j.trc.2021.103464).\n", + "Force-based models, which include the **Social Force Model (SFM)** and the **Generalized \n", + "Centrifugal Force Model (GCFM)**, excel at simulating physical interactions between pedestrians. \n", + "These models are particularly effective at capturing pushing behavior in dense crowds, making \n", + "them ideal for evacuation scenarios or situations where physical contact between pedestrians \n", + "is common. The **GCFM** offers some improvements over the basic **SFM**, particularly in handling \n", + "body shape effects.\n", "\n", - "When it comes to computational efficiency, velocity-based models generally have an advantage. The CFM offers the fastest execution times, while the AVM provides a good balance between computational efficiency and realistic behavior simulation. Force-based models, while more computationally intensive, are necessary when accurate physical interaction modeling is crucial.\n", + "### Velocity-Based Models\n", "\n", - "The choice of model ultimately comes down to your specific requirements. If you're simulating emergency evacuations or very crowded environments where physical interactions are important, a force-based model like SFM would be appropriate. For typical pedestrian scenarios where smooth navigation and realistic avoidance behavior are priority, the AVM would be the better choice. In cases where computational resources are limited and physical interactions are not critical, the CFM can provide adequate results.\n", + "On the other hand, velocity-based models like the **Collision-Free Model (CFM)** and the \n", + "**Anticipation Velocity Model (AVM)** are better suited for normal walking situations where \n", + "collision avoidance is the primary concern. These models typically produce smoother, more \n", + "realistic trajectories in regular-density scenarios. The **AVM**, in particular, stands out for \n", + "its superior collision avoidance capabilities and ability to reproduce lane formation behavior, \n", + "as demonstrated in [recent research](https://doi.org/10.1016/j.trc.2021.103464).\n", "\n", - "The key is to understand that no single model is universally superior – each has its place depending on the specific requirements of your simulation scenario.\n", + "### Computational Efficiency\n", "\n", + "When it comes to computational efficiency, velocity-based models generally have an advantage. \n", + "The **CFM** offers the fastest execution times, while the **AVM** provides a good balance between \n", + "computational efficiency and realistic behavior simulation. Force-based models, while more \n", + "computationally intensive, are necessary when accurate physical interaction modeling is crucial.\n", + "\n", + "### Model Selection Guidance\n", + "\n", + "The choice of model ultimately comes down to your specific requirements:\n", + "\n", + "- **Force-based models (SFM, GCFM):** Best for emergency evacuations or crowded environments \n", + " with significant physical interactions. \n", + "- **Velocity-based models (AVM):** Ideal for typical pedestrian scenarios requiring smooth \n", + " navigation and realistic avoidance behavior. \n", + "- **Collision-Free Model (CFM):** Suitable when computational resources are limited and \n", + " physical interactions are not critical. \n", + "\n", + "The key is to understand that no single model is universally superior—each has its place \n", + "depending on the specific requirements of your simulation scenario.\n", "\n", "**So as a final facit, which model to use? The answer is: it depends.**\n", "\n", "## Models Under Investigation\n", "\n", + "In this notebooks the models compared are:\n", + "\n", "1. [**Collision-Free Speed Model (CSM):**](https://pedestriandynamics.org/models/collision_free_speed_model/) \n", - " A velocity-based model focused on ensuring agents move without collisions by dynamically adjusting their speeds.\n", + " A velocity-based model focused on ensuring agents move without collisions \n", + " by dynamically adjusting their speeds.\n", "\n", "2. [**Anticipation Velocity Model (AVM):**](https://doi.org/10.1016/j.trc.2021.103464) \n", - " A model that incorporates anticipation and reaction times, allowing agents to predict and avoid potential collisions.\n", + " A model that incorporates anticipation and reaction times, allowing agents \n", + " to predict and avoid potential collisions.\n", "\n", "3. [**Social Force Model (SFM):**](https://pedestriandynamics.org/models/social_force_model/)\n", - " A force-based model where agents are influenced by attractive forces toward goals and repulsive forces from obstacles and other agents.\n", + " A force-based model where agents are influenced \n", + " by attractive forces toward goals and repulsive forces \n", + " from obstacles and other agents.\n", "\n", "4. [**Generalized Centrifugal Force Model (GCFM):**](https://pedestriandynamics.org/models/generalized_centrifugal_force_model/) \n", - " An enhanced force-based model where agents experience centrifugal forces to better simulate realistic avoidance behavior.\n", + " An enhanced force-based model where agents experience centrifugal forces \n", + " to better simulate realistic avoidance behavior.\n", "\n", "> **Note:** \n", - "> All models are utilized with their default parameter settings as defined in **JuPedSim**.\n", - "\n", - "## Simulation Workflow\n", - "\n", - "- **Environment Setup:**\n", - " Defining the simulation environment with walls and obstacles to challenge agent navigation.\n", - "\n", - "- **Agent Initialization:** \n", - " Assigning starting positions, desired speeds, and target goals for agents.\n", - "\n", - "- **Model Execution:** \n", - " Running the simulation for each model and recording agent trajectories.\n", - "\n", - "- **Visualization:** \n", - " Animating and displaying the results of all models side by side to enable direct comparison of their behaviors.\n", - "\n", - " Moreover. evacuation times for all runs are ploted per model.\n" + "> All models are utilized with their default parameter settings as defined in **JuPedSim**." ] }, {