First
This commit is contained in:
386
archive/source/test/_2_testing.py
Normal file
386
archive/source/test/_2_testing.py
Normal file
@@ -0,0 +1,386 @@
|
||||
import jupedsim as jps
|
||||
import shapely
|
||||
from dataclasses import dataclass
|
||||
from typing import List, Dict, Tuple
|
||||
import numpy as np
|
||||
import matplotlib
|
||||
matplotlib.use('QtAgg')
|
||||
import matplotlib.pyplot as plt
|
||||
from PyQt6 import QtWidgets
|
||||
import sys
|
||||
import config
|
||||
sys.path.insert(0,str(config.GEO_DIR))
|
||||
from geo_current import geo_current
|
||||
|
||||
@dataclass
|
||||
class AgentSetup:
|
||||
id:int
|
||||
grade:str
|
||||
door:int
|
||||
speed:float
|
||||
radius:float
|
||||
spawn:Tuple[float,float]
|
||||
|
||||
@dataclass
|
||||
class SimSetup:
|
||||
doorways:Dict[int,shapely.Polygon]
|
||||
grades:Dict[str,Dict]
|
||||
min_spacing:float=0.6
|
||||
total_sim_time:float=200.0
|
||||
door_capacity:int=10
|
||||
walkable_area:shapely.Polygon
|
||||
exit_area:shapely.Polygon
|
||||
|
||||
class EvacSim:
|
||||
def __init__(self,setup:SimSetup):
|
||||
self.setup = setup
|
||||
self.all_agents = []
|
||||
self.all_spawn_events = []
|
||||
self.simulation = None
|
||||
self.exit_id = None
|
||||
self.doorway_system = {}
|
||||
|
||||
def run(self):
|
||||
self.all_agents = self.agent_params()
|
||||
self.setup_sim_env()
|
||||
self.spawn_events = self.get_spawn_events()
|
||||
self.run_sim()
|
||||
|
||||
def agent_params(self)->List[AgentSetup]:
|
||||
agent_id = 1
|
||||
rng = np.random.default_rng(seed=42)
|
||||
all_agents = []
|
||||
for grade in self.setup.grades.keys():
|
||||
spawn_time = rng.uniform(0.0,115.0)
|
||||
self.setup.grades[grade]["Spawn Time"] = spawn_time
|
||||
gr_agent_num = int(self.setup.grades[grade]["Pop Current"])
|
||||
door = int(self.setup.grades[grade]["Door"])
|
||||
current_agent = 0
|
||||
for num in range(gr_agent_num):
|
||||
speed = rng.normal(
|
||||
loc=self.setup.grades[grade]["Speed Mean"],
|
||||
scale=self.setup.grades[grade]["Speed Std Dev"],
|
||||
size=1)
|
||||
radius = self.setup.grades[grade]["Radius"]
|
||||
new_agent = AgentSetup(
|
||||
id=agent_id,
|
||||
grade=grade,
|
||||
door=door,
|
||||
speed=speed,
|
||||
radius = radius,
|
||||
)
|
||||
all_agents.append(new_agent)
|
||||
agent_id += 1
|
||||
current_agent += 1
|
||||
return all_agents
|
||||
|
||||
def setup_sim_env(self):
|
||||
walkable_area = self.setup.walkable_area
|
||||
model = jps.CollisionFreeSpeedModel()
|
||||
self.simulation = jps.Simulation(
|
||||
model=model,geometry=walkable_area)
|
||||
self.exit_id = self.simulation.add_exit_stage(
|
||||
self.setup.exit_polygon)
|
||||
def doorway_system(self, door_id: int, door_polygon: shapely.Polygon):
|
||||
def get_waiting_area(self,door_polygon:shapely.Polygon)->shapely.Polygon:
|
||||
waiting_area = door_polygon.buffer(2.0, join_style=2)
|
||||
waiting_area = waiting_area.difference(door_polygon)
|
||||
|
||||
if waiting_area.geom_type == 'MultiPolygon':
|
||||
waiting_area = max(waiting_area.geoms, key=lambda p: p.area)
|
||||
return waiting_area
|
||||
|
||||
waiting_area = get_waiting_area(door_polygon)
|
||||
waiting_set_id = self.simulation.add_waiting_set_stage(waiting_area)
|
||||
|
||||
door_centroid = door_polygon.centroid
|
||||
queue_waypoints = [
|
||||
self.simulation.add_waypoint_stage((door_centroid.x, door_centroid.y - 1.0), 0.5),
|
||||
self.simulation.add_waypoint_stage((door_centroid.x, door_centroid.y), 0.5),
|
||||
self.simulation.add_waypoint_stage((door_centroid.x, door_centroid.y + 1.0), 0.5)
|
||||
]
|
||||
journey_stages = [waiting_set_id] + queue_waypoints + [self.exit_id]
|
||||
journey = jps.JourneyDescription(journey_stages)
|
||||
journey_id = self.simulation.add_journey(journey)
|
||||
|
||||
self.doorway_info[door_id] = {
|
||||
"waiting_area": waiting_area,
|
||||
"waiting_set_id": waiting_set_id,
|
||||
"queue_waypoints": queue_waypoints,
|
||||
"journey_id": journey_id,
|
||||
"door_polygon": door_polygon
|
||||
}
|
||||
for door_id, door_polygon in self.setup.doorways.items():
|
||||
self.doorway_system(door_id, door_polygon)
|
||||
|
||||
def get_spawn_events(self)->List[Dict]:
|
||||
events = []
|
||||
agents_by_grade = {}
|
||||
def get_spawn_point(self,door:int,num_points:int)->List[Tuple[float,float]]:
|
||||
polygon = self.setup.doorways[door]
|
||||
min_x,min_y,max_x,max_y = polygon.bounds
|
||||
points = []
|
||||
attempts = 0
|
||||
max_attempts = num_points * 100
|
||||
while len(points) < num_points and attempts < max_attempts:
|
||||
x = random.uniform(min_x, max_x)
|
||||
y = random.uniform(min_y, max_y)
|
||||
point = shapely.Point(x, y)
|
||||
if polygon.contains(point):
|
||||
too_close = False
|
||||
for existing in points:
|
||||
if np.sqrt((x - existing[0])**2 + (y - existing[1])**2) < self.setup.min_spacing:
|
||||
too_close = True
|
||||
break
|
||||
if not too_close:
|
||||
points.append((x, y))
|
||||
attempts += 1
|
||||
return points[:num_points]
|
||||
for agent in self.all_agents:
|
||||
for grade_name, grade_info in self.setup.grades.items():
|
||||
if agent.door == grade_info["Door"]:
|
||||
if grade_name not in agents_by_grade:
|
||||
agents_by_grade[grade_name] = []
|
||||
agents_by_grade[grade_name].append(agent)
|
||||
break
|
||||
for grade_name, grade_info in self.setup.grades.items():
|
||||
door_id = grade_info["Door"]
|
||||
spawn_time = grade_info["Spawn Time"]
|
||||
grade_agents = agents_by_group.get(grade_name, [])
|
||||
if not grade_agents:
|
||||
continue
|
||||
door_polygon = self.setup.doorways[door_id]
|
||||
spawn_positions = self.get_spawn_point(
|
||||
door_polygon,
|
||||
len(group_agents))
|
||||
for agent, position in zip(group_agents, spawn_positions):
|
||||
events.append({
|
||||
"time": spawn_time,
|
||||
"agent": agent,
|
||||
"position": position,
|
||||
"grade": grade_name,
|
||||
"door": door_id
|
||||
})
|
||||
events.sort(key=lambda x: x["time"])
|
||||
return events
|
||||
|
||||
def run_sim(self):
|
||||
spawned_event_indices = set()
|
||||
agents_in_door_area = {door_id: 0 for door_id in self.config.door_polygons.keys()}
|
||||
event_index = 0
|
||||
|
||||
print("\nStarting Simulation Loop...")
|
||||
print(f"Total Simulation Time: {self.config.total_simulation_time}s")
|
||||
print(f"Door Capacity: {self.config.door_capacity} agents per door")
|
||||
|
||||
while self.simulation.elapsed_time() < self.config.total_simulation_time:
|
||||
current_time = self.simulation.elapsed_time()
|
||||
self._process_spawn_events(
|
||||
current_time,
|
||||
event_index,
|
||||
spawned_event_indices,
|
||||
agents_in_door_area)
|
||||
while (event_index < len(self.spawn_events) and \
|
||||
self.spawn_events[event_index]["time"] <= current_time and \
|
||||
event_index in spawned_event_indices):
|
||||
event_index += 1
|
||||
self.simulation.iterate()
|
||||
|
||||
print(f"\nSimulation completed at {self.simulation.elapsed_time():.2f} seconds")
|
||||
|
||||
def process_spawn_events(
|
||||
self,
|
||||
current_time: float,
|
||||
event_index: int,
|
||||
spawned_events: set,
|
||||
agents_in_door_area: Dict
|
||||
):
|
||||
while (event_idx < len(self.spawn_events) and \
|
||||
self.spawn_events[event_idx]["time"] <= current_time and \
|
||||
event_idx not in spawned_events):
|
||||
event = self.spawn_events[event_idx]
|
||||
door_id = event["door"]
|
||||
agent = event["agent"]
|
||||
if agents_in_door_area[door_id] < self.setup.door_capacity:
|
||||
self.spawn_agent(event,door_id,agent)
|
||||
agents_in_door_area[door_id] += 1
|
||||
spawned_events.add(event_idx)
|
||||
event_index += 1
|
||||
|
||||
def spawn_agent(self,event:Dict,door_id:int,agent:AgentSetup):
|
||||
journey_id = self.doorway_systems[door_id]["journey_id"]
|
||||
|
||||
agent_params = jps.CollisionFreeSpeedModelAgentParameters(
|
||||
position=event["position"],
|
||||
journey_id=journey_id,
|
||||
stage_id=self.doorway_system[door_id]["waiting_set_id"],
|
||||
radius=agent.radius,
|
||||
v0=agent.speed,
|
||||
)
|
||||
|
||||
agent_id = self.simulation.add_agent(agent_params)
|
||||
|
||||
# Optional: Log spawning
|
||||
if agent_id % 50 == 0: # Log every 50th agent
|
||||
print(f" Spawned agent {agent_id} (group: {event['group']}, door: {door_id})")
|
||||
|
||||
|
||||
def start_sim_run():
|
||||
print("Evacuation Simulation")
|
||||
print("-" * 40)
|
||||
geometry,[door0,door1,door2,exit_door] = geo_current(full_plot = True)
|
||||
door_polygons = {
|
||||
1: door0,
|
||||
2: door1,
|
||||
3: door2
|
||||
}
|
||||
grade_data = {
|
||||
"Kindergarden":{
|
||||
"Door":0,
|
||||
"Pop Current":34,
|
||||
"Pop Mean":31.43,
|
||||
"Pop Std Dev":5.65,
|
||||
"Speed Mean":1.21,
|
||||
"Speed Std Dev":0.24,
|
||||
"Radius":0.407,
|
||||
"Spawn Time":None
|
||||
},
|
||||
"Grade 1":{
|
||||
"Door":0,
|
||||
"Pop Current":26,
|
||||
"Pop Mean":32.57,
|
||||
"Pop Std Dev":6.27,
|
||||
"Speed Mean":1.35,
|
||||
"Speed Std Dev":0.26,
|
||||
"Radius":0.407,
|
||||
"Spawn Time":None
|
||||
},
|
||||
"Grade 2":{
|
||||
"Door":0,
|
||||
"Pop Current":42,
|
||||
"Pop Mean":34.43,
|
||||
"Pop Std Dev":6.80,
|
||||
"Speed Mean":1.42,
|
||||
"Speed Std Dev":0.28,
|
||||
"Radius":0.407,
|
||||
"Spawn Time":None
|
||||
},
|
||||
"Grade 3":{
|
||||
"Door":0,
|
||||
"Pop Current":39,
|
||||
"Pop Mean":35.43,
|
||||
"Pop Std Dev":5.19,
|
||||
"Speed Mean":1.48,
|
||||
"Speed Std Dev":0.23,
|
||||
"Radius":0.407,
|
||||
"Spawn Time":None
|
||||
},
|
||||
"Grade 4":{
|
||||
"Door":1,
|
||||
"Pop Current":30,
|
||||
"Pop Mean":34.86,
|
||||
"Pop Std Dev":6.77,
|
||||
"Speed Mean":1.58,
|
||||
"Speed Std Dev":0.26,
|
||||
"Radius":0.417,
|
||||
"Spawn Time":None
|
||||
},
|
||||
"Grade 5":{
|
||||
"Door":1,
|
||||
"Pop Current":43,
|
||||
"Pop Mean":36.71,
|
||||
"Pop Std Dev":7.09,
|
||||
"Speed Mean":1.59,
|
||||
"Speed Std Dev":0.24,
|
||||
"Radius":0.434,
|
||||
"Spawn Time":None
|
||||
},
|
||||
"Grade 6":{
|
||||
"Door":1,
|
||||
"Pop Current":29,
|
||||
"Pop Mean":37.71,
|
||||
"Pop Std Dev":6.99,
|
||||
"Speed Mean":1.65,
|
||||
"Speed Std Dev":0.24,
|
||||
"Radius":0.454,
|
||||
"Spawn Time":None
|
||||
},
|
||||
"Grade 7":{
|
||||
"Door":2,
|
||||
"Pop Current":45,
|
||||
"Pop Mean":40.43,
|
||||
"Pop Std Dev":6.02,
|
||||
"Speed Mean":1.61,
|
||||
"Speed Std Dev":0.25,
|
||||
"Radius":0.471,
|
||||
"Spawn Time":None
|
||||
},
|
||||
"Grade 8":{
|
||||
"Door":2,
|
||||
"Pop Current":36,
|
||||
"Pop Mean":40.43,
|
||||
"Pop Std Dev":5.50,
|
||||
"Speed Mean":1.66,
|
||||
"Speed Std Dev":0.24,
|
||||
"Radius":0.488,
|
||||
"Spawn Time":None
|
||||
},
|
||||
"Grade 9":{
|
||||
"Door":2,
|
||||
"Pop Current":44,
|
||||
"Pop Mean":44.14,
|
||||
"Pop Std Dev":4.85,
|
||||
"Speed Mean":1.60,
|
||||
"Speed Std Dev":0.24,
|
||||
"Radius":0.500,
|
||||
"Spawn Time":None
|
||||
},
|
||||
"Grade 10":{
|
||||
"Door":2,
|
||||
"Pop Current":36,
|
||||
"Pop Mean":46.29,
|
||||
"Pop Std Dev":6.29,
|
||||
"Speed Mean":1.57,
|
||||
"Speed Std Dev":0.23,
|
||||
"Radius":0.507,
|
||||
"Spawn Time":None
|
||||
},
|
||||
"Grade 11":{
|
||||
"Door":2,
|
||||
"Pop Current":54,
|
||||
"Pop Mean":48.29,
|
||||
"Pop Std Dev":3.30,
|
||||
"Speed Mean":1.51,
|
||||
"Speed Std Dev":0.22,
|
||||
"Radius":0.515,
|
||||
"Spawn Time":None
|
||||
},
|
||||
"Grade 12":{
|
||||
"Door":2,
|
||||
"Pop Current":46,
|
||||
"Pop Mean":43.71,
|
||||
"Pop Std Dev":6.02,
|
||||
"Speed Mean":1.54,
|
||||
"Speed Std Dev":0.23,
|
||||
"Radius":0.520,
|
||||
"Spawn Time":None
|
||||
}}
|
||||
|
||||
config = SimSetup(
|
||||
doorways=door_polygons,
|
||||
grades=grade_data,
|
||||
total_simulation_time=180.0,
|
||||
door_capacity=10,
|
||||
walkable_area=geometry,
|
||||
exit_area=exit_door
|
||||
)
|
||||
|
||||
sim = EvacSim(config)
|
||||
return sim.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
simulation = start_sim_run()
|
||||
print(f"\nFinal simulation state:")
|
||||
print(f" Elapsed time: {simulation.elapsed_time():.2f}s")
|
||||
|
||||
Reference in New Issue
Block a user