First
This commit is contained in:
BIN
archive/source/__pycache__/config.cpython-313.pyc
Normal file
BIN
archive/source/__pycache__/config.cpython-313.pyc
Normal file
Binary file not shown.
17
archive/source/sim_agents/config.py
Normal file
17
archive/source/sim_agents/config.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
E.Drake - ENGN-2220
|
||||
|
||||
Thu Jan 22 23:48:50 2026
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).parent.parent.parent
|
||||
SOURCE_DIR = ROOT/"source"
|
||||
ARCHIVE_DIR = ROOT/"archive"
|
||||
PATH_DIR = ROOT/"path"
|
||||
AGENTS_DIR = ROOT/SOURCE_DIR/"sim_agents"
|
||||
GEO_DIR = ROOT/SOURCE_DIR/"sim_geometry"
|
||||
TEST_DIR = ROOT/SOURCE_DIR/"test"
|
||||
|
||||
|
||||
72
archive/source/sim_agents/traits.py
Normal file
72
archive/source/sim_agents/traits.py
Normal file
@@ -0,0 +1,72 @@
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
grades = {
|
||||
"Kindergarden":np.array(
|
||||
[31.43,5.65,1.21,0.24]
|
||||
),
|
||||
"Grade 1":np.array(
|
||||
[32.57,6.27,1.35,0.26]
|
||||
),
|
||||
"Grade 2":np.array(
|
||||
[34.43,6.80,1.42,0.28]
|
||||
),
|
||||
"Grade 3":np.array(
|
||||
[35.43,5.19,1.48,0.23]
|
||||
),
|
||||
"Grade 4":np.array(
|
||||
[34.86,6.77,1.58,0.26]
|
||||
),
|
||||
"Grade 5":np.array(
|
||||
[36.71,7.09,1.59,0.24]
|
||||
),
|
||||
"Grade 6":np.array(
|
||||
[37.71,6.99,1.65,0.24]
|
||||
),
|
||||
"Grade 7":np.array(
|
||||
[40.43,6.02,1.61,0.25]
|
||||
),
|
||||
"Grade 8":np.array(
|
||||
[40.43,5.50,1.66,0.24]
|
||||
),
|
||||
"Grade 9":np.array(
|
||||
[44.14,4.85,1.60,0.24]
|
||||
),
|
||||
"Grade 10":np.array(
|
||||
[46.29,6.29,1.57,0.23]
|
||||
),
|
||||
"Grade 11":np.array(
|
||||
[48.29,3.30,1.51,0.22]
|
||||
),
|
||||
"Grade 12":np.array(
|
||||
[43.71,6.02,1.54,0.23]
|
||||
)}
|
||||
|
||||
df_srs_data=pd.DataFrame({
|
||||
"Grade Level":(
|
||||
list(grades.keys())),
|
||||
"Pop Mean":[
|
||||
grades[j][0] for j in grades],
|
||||
"Pop Std Dev":[
|
||||
grades[j][1] for j in grades],
|
||||
"Speed Mean":[
|
||||
grades[j][2] for j in grades],
|
||||
"Speed Std Dev":[
|
||||
grades[j][3] for j in grades]})
|
||||
|
||||
@dataclass
|
||||
class AgentConfig:
|
||||
id:int
|
||||
grade:str
|
||||
door:str
|
||||
speed:float
|
||||
radius:float
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
91
archive/source/sim_agents/traits_current.py
Normal file
91
archive/source/sim_agents/traits_current.py
Normal file
@@ -0,0 +1,91 @@
|
||||
import numpy as np
|
||||
from dataclasses import dataclass
|
||||
from typing import List, Dict, Optional
|
||||
from collections import defaultdict
|
||||
|
||||
##https://censusatschool.ca/data-results/2017-2018/average-height-by-age/
|
||||
@dataclass
|
||||
class AgentConfig:
|
||||
id:int
|
||||
grade:str
|
||||
door:int
|
||||
speed:float
|
||||
radius:float
|
||||
|
||||
def agent_params():
|
||||
gr_data = {
|
||||
# [0]: number of students
|
||||
# [1]: door number
|
||||
# [2]: speed mean
|
||||
# [3]: speed standard deviation
|
||||
# [4]: radius mean
|
||||
"Kindergarden":np.array(
|
||||
[34,0,1.21,0.24,0.407]
|
||||
),
|
||||
"Grade 1":np.array(
|
||||
[26,0,1.35,0.26,0.407]
|
||||
),
|
||||
"Grade 2":np.array(
|
||||
[42,0,1.42,0.28,0.407]
|
||||
),
|
||||
"Grade 3":np.array(
|
||||
[39,0,1.48,0.23,0.407]
|
||||
),
|
||||
"Grade 4":np.array(
|
||||
[30,1,1.58,0.26,0.417]
|
||||
),
|
||||
"Grade 5":np.array(
|
||||
[43,1,1.59,0.24,0.434]
|
||||
),
|
||||
"Grade 6":np.array(
|
||||
[29,1,1.65,0.24,0.454]
|
||||
),
|
||||
"Grade 7":np.array(
|
||||
[45,2,1.61,0.25,0.471]
|
||||
),
|
||||
"Grade 8":np.array(
|
||||
[36,2,1.66,0.24,0.488]
|
||||
),
|
||||
"Grade 9":np.array(
|
||||
[44,2,1.60,0.24,0.500]
|
||||
),
|
||||
"Grade 10":np.array(
|
||||
[36,2,1.57,0.23,0.507]
|
||||
),
|
||||
"Grade 11":np.array(
|
||||
[54,2,1.51,0.22,0.515]
|
||||
),
|
||||
"Grade 12":np.array(
|
||||
[46,2,1.54,0.23,0.520]
|
||||
)}
|
||||
agent_id = 1
|
||||
rng = np.random.default_rng(seed=42)
|
||||
all_agents = []
|
||||
gr_agents = []
|
||||
for grade in gr_data:
|
||||
for num in range(int(gr_data[grade][0])):
|
||||
door = gr_data[grade][1]
|
||||
speed = rng.normal(
|
||||
loc=gr_data[grade][2],
|
||||
scale=gr_data[grade][3],
|
||||
size=1)
|
||||
radius = gr_data[grade][4]
|
||||
gr_agents.append(
|
||||
AgentConfig(
|
||||
id=agent_id,
|
||||
grade=grade,
|
||||
door=door,
|
||||
speed=speed,
|
||||
radius = radius
|
||||
))
|
||||
agent_id += 1
|
||||
all_agents.append(gr_agents)
|
||||
gr_agents = []
|
||||
#for grade in all_agents:
|
||||
# for agent in grade:
|
||||
# print(agent)
|
||||
return all_agents
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
archive/source/sim_geometry/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
archive/source/sim_geometry/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
17
archive/source/sim_geometry/config.py
Normal file
17
archive/source/sim_geometry/config.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
E.Drake - ENGN-2220
|
||||
|
||||
Thu Jan 22 23:48:50 2026
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).parent.parent.parent
|
||||
SOURCE_DIR = ROOT/"source"
|
||||
ARCHIVE_DIR = ROOT/"archive"
|
||||
PATH_DIR = ROOT/"path"
|
||||
AGENTS_DIR = ROOT/SOURCE_DIR/"sim_agents"
|
||||
GEO_DIR = ROOT/SOURCE_DIR/"sim_geometry"
|
||||
TEST_DIR = ROOT/SOURCE_DIR/"test"
|
||||
|
||||
|
||||
147
archive/source/sim_geometry/geo_current.py
Normal file
147
archive/source/sim_geometry/geo_current.py
Normal file
@@ -0,0 +1,147 @@
|
||||
import sys
|
||||
import matplotlib
|
||||
matplotlib.use('QtAgg')
|
||||
import matplotlib.pyplot as plt
|
||||
from shapely import Polygon
|
||||
from shapely.plotting import plot_polygon
|
||||
|
||||
def geo_current(full_plot:bool=False):
|
||||
A_crosswalk=Polygon([
|
||||
(-1,1.499),
|
||||
(-1,3.327),
|
||||
(0,3.327),
|
||||
(11.214, 3.327),
|
||||
(11.214,1.499),
|
||||
(0,1.499)
|
||||
])
|
||||
B_queue=Polygon([
|
||||
(11.214, 0),
|
||||
(22.163, 0),
|
||||
(22.163, 4.826),
|
||||
(11.214, 4.826)
|
||||
])
|
||||
C_road_adj_path=Polygon([
|
||||
(21.787,4.826),
|
||||
(24.214,4.826),
|
||||
(24.214,40.431),
|
||||
(29.179,40.431),
|
||||
(29.179,42.511),
|
||||
(24.214,42.511),
|
||||
(21.787,42.511)
|
||||
])
|
||||
D_path_k_3=Polygon([
|
||||
(26.45,42.511),
|
||||
(26.45,52.84),
|
||||
(26.45,53.84),
|
||||
(29.179,53.84),
|
||||
(29.179,52.84),
|
||||
(29.179,42.511)
|
||||
])
|
||||
E_path_4_6=Polygon([
|
||||
(29.179,42.511),
|
||||
(54.351,42.511),
|
||||
(60.406,48.842),
|
||||
(60.406,51.22),
|
||||
(60.406,52.22),
|
||||
(63.49,52.22),
|
||||
(63.49,51.22),
|
||||
(63.49,47.866),
|
||||
(56.381,40.431),
|
||||
(29.179,40.431)
|
||||
])
|
||||
F_path_7_12=Polygon([
|
||||
(22.163, 0),
|
||||
(39.227, 5.516),
|
||||
(39.631, 4.267),
|
||||
(39.939,3.315),
|
||||
(45.099,4.983),
|
||||
(44.792,5.935),
|
||||
(43.169,10.954),
|
||||
(24.214,4.826),
|
||||
(22.163,4.826)
|
||||
])
|
||||
G_extended_queue=Polygon([
|
||||
(11.214,0),
|
||||
(12.924,0),
|
||||
(12.924,-4.569),
|
||||
(11.214,-4.569)
|
||||
])
|
||||
H_angled_path=Polygon([
|
||||
(21.787,13.192),
|
||||
(21.787,10.527),
|
||||
(17,4.826),
|
||||
(14.767,4.826)
|
||||
])
|
||||
enter_k_3=Polygon([
|
||||
(26.45,52.84),
|
||||
(29.179,52.84),
|
||||
(29.179,53.84),
|
||||
(26.45,53.84)
|
||||
])
|
||||
enter_4_6=Polygon([
|
||||
(60.406,51.22),
|
||||
(60.406,52.22),
|
||||
(63.49,52.22),
|
||||
(63.49,51.22)
|
||||
])
|
||||
enter_7_12=Polygon([
|
||||
(39.631, 4.267),
|
||||
(39.939,3.315),
|
||||
(45.099,4.983),
|
||||
(44.792,5.935)
|
||||
])
|
||||
exit_polygon=Polygon([
|
||||
(0,1.499),
|
||||
(0,3.327),
|
||||
(-1,3.327),
|
||||
(-1,1.499)
|
||||
])
|
||||
|
||||
geometry = (
|
||||
A_crosswalk.union(
|
||||
B_queue).union(
|
||||
C_road_adj_path).union(
|
||||
D_path_k_3).union(
|
||||
E_path_4_6).union(
|
||||
F_path_7_12).union(
|
||||
G_extended_queue).union(
|
||||
H_angled_path)
|
||||
)
|
||||
doors = [
|
||||
enter_k_3,
|
||||
enter_4_6,
|
||||
enter_7_12,
|
||||
exit_polygon
|
||||
]
|
||||
|
||||
if full_plot is False:
|
||||
plot_polygon(A_crosswalk,color="black",add_points=False)
|
||||
plot_polygon(B_queue,color="black",add_points=False)
|
||||
plot_polygon(C_road_adj_path, color="blue",add_points=False)
|
||||
plot_polygon(D_path_k_3, color="blue",add_points=False)
|
||||
plot_polygon(E_path_4_6, color="blue",add_points=False)
|
||||
plot_polygon(F_path_7_12, color="blue",add_points=False)
|
||||
plot_polygon(G_extended_queue, color="black",add_points=False)
|
||||
plot_polygon(H_angled_path, color="black",add_points=False)
|
||||
|
||||
plot_polygon(enter_k_3, color="darkgreen",add_points=False)
|
||||
plot_polygon(enter_4_6, color="darkgreen",add_points=False)
|
||||
plot_polygon(enter_7_12, color="darkgreen",add_points=False)
|
||||
|
||||
plot_polygon(exit_polygon, color="orangered",add_points=False)
|
||||
|
||||
else:
|
||||
plot_polygon(geometry,color="blue",add_points=False)
|
||||
plot_polygon(enter_k_3,color="red",add_points=False)
|
||||
plot_polygon(enter_4_6,color="red",add_points=False)
|
||||
plot_polygon(enter_7_12,color="red",add_points=False)
|
||||
|
||||
return geometry, doors
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from PyQt6 import QtWidgets
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
geometry,doors = geo_current(True)
|
||||
plt.show(block=False)
|
||||
sys.exit(app.exec())
|
||||
71
archive/source/test/_1_testing.py
Normal file
71
archive/source/test/_1_testing.py
Normal file
@@ -0,0 +1,71 @@
|
||||
"""
|
||||
E.Drake - ENGN 2220
|
||||
Jan 21, 2026
|
||||
|
||||
TESTING GEOMETRY
|
||||
"""
|
||||
import matplotlib
|
||||
matplotlib.use('QtAgg')
|
||||
import matplotlib.pyplot as plt
|
||||
from PyQt6 import QtWidgets
|
||||
import sys
|
||||
import config
|
||||
#print(str(config.GEO_DIR))
|
||||
sys.path.insert(0,str(config.GEO_DIR))
|
||||
sys.path.insert(0,str(config.PATH_DIR))
|
||||
from geo_current import geo_current
|
||||
|
||||
import jupedsim as jps
|
||||
from matplotlib.patches import Circle
|
||||
|
||||
def main_loop():
|
||||
geometry,doors = geo_current(full_plot = True)
|
||||
dk_3, d4_6, d7_12, d_exit = doors
|
||||
|
||||
model = jps.CollisionFreeSpeedModel()
|
||||
sim = jps.Simulation(model=model,geometry=geometry)
|
||||
exit_id = sim.add_exit_stage(d_exit)
|
||||
journey = jps.JourneyDescription([exit_id])
|
||||
journey_id = sim.add_journey(journey)
|
||||
total_sim_time = 60.0
|
||||
|
||||
doorways = {
|
||||
0: dk_3,
|
||||
1: d4_6,
|
||||
2: d7_12,
|
||||
}
|
||||
|
||||
# Spawn times for each door (seconds)
|
||||
spawn_schedule = {
|
||||
"door_1": [0.0, 5.0, 10.0], # Agents at t=0, 5, 10
|
||||
"door_2": [2.0, 7.0],
|
||||
"door_3": [3.0],
|
||||
}
|
||||
events = []
|
||||
for door_name, times in spawn_schedule.items():
|
||||
for t in times:
|
||||
events.append((t, doors[door_name]))
|
||||
events.sort(key=lambda x: x[0])
|
||||
|
||||
event_index = 0
|
||||
while sim.elapsed_time() < total_sim_time:
|
||||
current_time = sim.elapsed_time()
|
||||
# Process all events whose time has come
|
||||
while event_index < len(events) and events[event_index][0] <= current_time:
|
||||
_, door_pos = events[event_index]
|
||||
agent_params = jps.CollisionFreeSpeedModelAgentParameters(
|
||||
position=door_pos,
|
||||
journey_id=journey_id,
|
||||
stage_id=exit_id,
|
||||
radius=0.2,
|
||||
)
|
||||
sim.add_agent(agent_params)
|
||||
event_index += 1
|
||||
sim.iterate()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
main_loop()
|
||||
plt.show(block=False)
|
||||
sys.exit(app.exec())
|
||||
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")
|
||||
|
||||
BIN
archive/source/test/__pycache__/config.cpython-310.pyc
Normal file
BIN
archive/source/test/__pycache__/config.cpython-310.pyc
Normal file
Binary file not shown.
BIN
archive/source/test/__pycache__/config.cpython-312.pyc
Normal file
BIN
archive/source/test/__pycache__/config.cpython-312.pyc
Normal file
Binary file not shown.
BIN
archive/source/test/__pycache__/config.cpython-313.pyc
Normal file
BIN
archive/source/test/__pycache__/config.cpython-313.pyc
Normal file
Binary file not shown.
388
archive/source/test/_test_example_.py
Normal file
388
archive/source/test/_test_example_.py
Normal file
@@ -0,0 +1,388 @@
|
||||
import jupedsim as jps
|
||||
import shapely
|
||||
import random
|
||||
from dataclasses import dataclass
|
||||
from typing import List, Dict, Tuple, Optional
|
||||
import numpy as np
|
||||
|
||||
@dataclass
|
||||
class AgentConfig:
|
||||
id: int
|
||||
grade: str
|
||||
door: int
|
||||
speed: float
|
||||
radius: float
|
||||
|
||||
@dataclass
|
||||
class SimulationConfig:
|
||||
door_polygons: Dict[int, shapely.Polygon]
|
||||
groups: Dict[str, Dict]
|
||||
total_simulation_time: float = 300.0
|
||||
door_capacity: int = 10
|
||||
min_spacing: float = 0.6
|
||||
|
||||
"""
|
||||
def __post_init__(self):
|
||||
'''Set default walkable area and exit polygon if not provided.'''
|
||||
if self.walkable_area_coords is None:
|
||||
self.walkable_area_coords = [(0, 0), (50, 0), (50, 30), (0, 30)]
|
||||
if self.exit_polygon_coords is None:
|
||||
self.exit_polygon_coords = [(45, 10), (48, 10), (48, 20), (45, 20)]
|
||||
"""
|
||||
|
||||
class PedestrianSimulation:
|
||||
"""
|
||||
Main class for running pedestrian simulations with door queues and scheduled spawning.
|
||||
|
||||
Architecture Flow:
|
||||
1. Configuration Setup
|
||||
↓
|
||||
2. Agent Configuration Generation
|
||||
↓
|
||||
3. Geometry Preparation (Walkable area, Doors, Exit)
|
||||
↓
|
||||
4. Door System Setup (Waiting areas, Queues, Journeys)
|
||||
↓
|
||||
5. Spawn Event Precomputation
|
||||
↓
|
||||
6. Simulation Execution with Dynamic Spawning
|
||||
↓
|
||||
7. Results Analysis/Visualization
|
||||
"""
|
||||
|
||||
def __init__(self, config: SimulationConfig):
|
||||
self.config = config
|
||||
self.simulation = None
|
||||
self.door_systems = {}
|
||||
self.all_agents = []
|
||||
self.spawn_events = []
|
||||
self.exit_id = None
|
||||
|
||||
def run(self) -> jps.Simulation:
|
||||
"""
|
||||
Main orchestrator: Run the complete simulation.
|
||||
|
||||
Steps:
|
||||
1. Create agent configurations
|
||||
2. Setup simulation environment
|
||||
3. Precompute spawn events
|
||||
4. Execute simulation with dynamic spawning
|
||||
5. Return completed simulation object
|
||||
"""
|
||||
print("=" * 60)
|
||||
print("PEDESTRIAN SIMULATION STARTING")
|
||||
print("=" * 60)
|
||||
|
||||
self.all_agents = self._create_agent_configurations()
|
||||
print(f"Created {len(self.all_agents)} agent configurations")
|
||||
|
||||
self._setup_simulation_environment()
|
||||
print("Simulation environment setup complete")
|
||||
|
||||
self.spawn_events = self._precompute_spawn_events()
|
||||
print(f"Precomputed {len(self.spawn_events)} spawn events")
|
||||
|
||||
self._execute_simulation()
|
||||
print("Simulation execution complete")
|
||||
return self.simulation
|
||||
|
||||
def _create_agent_configurations(self) -> List[AgentConfig]:
|
||||
"""Create AgentConfig objects for all agents in all groups."""
|
||||
all_agents = []
|
||||
agent_id = 0
|
||||
|
||||
for group_name, group_info in self.config.groups.items():
|
||||
door = group_info["door"]
|
||||
size = group_info["size"]
|
||||
|
||||
for i in range(size):
|
||||
grade = random.choice(["A", "B", "C", "D", "F"])
|
||||
speed = random.uniform(1.0, 1.5) # m/s
|
||||
radius = random.uniform(0.2, 0.3) # meters
|
||||
|
||||
all_agents.append(AgentConfig(
|
||||
id=agent_id,
|
||||
grade=grade,
|
||||
door=door,
|
||||
speed=speed,
|
||||
radius=radius
|
||||
))
|
||||
agent_id += 1
|
||||
|
||||
return all_agents
|
||||
# includes id, grade, door, speed, and radius
|
||||
|
||||
def _generate_spawn_points(self, polygon: shapely.Polygon,num_points: int) -> List[Tuple[float, float]]:
|
||||
"""Generate non-overlapping spawn points within a polygon."""
|
||||
points = []
|
||||
min_x, min_y, max_x, max_y = polygon.bounds
|
||||
|
||||
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.config.min_spacing:
|
||||
too_close = True
|
||||
break
|
||||
|
||||
if not too_close:
|
||||
points.append((x, y))
|
||||
|
||||
attempts += 1
|
||||
return points[:num_points]
|
||||
# get list of spawn point tuples to provide to agents
|
||||
|
||||
def _create_waiting_area(self, door_polygon: shapely.Polygon) -> shapely.Polygon:
|
||||
"""Create a waiting area adjacent to the door 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
|
||||
|
||||
def _setup_simulation_environment(self):
|
||||
"""Setup the simulation with door queues and waiting areas."""
|
||||
# Create walkable area geometry
|
||||
walkable_area = shapely.Polygon(self.config.walkable_area_coords)
|
||||
|
||||
# Create model and simulation
|
||||
model = jps.CollisionFreeSpeedModel()
|
||||
self.simulation = jps.Simulation(model=model, geometry=walkable_area)
|
||||
|
||||
# Define exit zone
|
||||
exit_polygon = shapely.Polygon(self.config.exit_polygon_coords)
|
||||
self.exit_id = self.simulation.add_exit_stage(exit_polygon)
|
||||
|
||||
# Create door systems
|
||||
for door_id, door_polygon in self.config.door_polygons.items():
|
||||
self._setup_door_system(door_id, door_polygon)
|
||||
|
||||
def _setup_door_system(self, door_id: int, door_polygon: shapely.Polygon):
|
||||
"""Setup queue system for a specific door."""
|
||||
# Create waiting area
|
||||
waiting_area = self._create_waiting_area(door_polygon)
|
||||
waiting_set_id = self.simulation.add_waiting_set_stage(waiting_area)
|
||||
|
||||
# Create queue waypoints
|
||||
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)
|
||||
]
|
||||
|
||||
# Create journey
|
||||
journey_stages = [waiting_set_id] + queue_waypoints + [self.exit_id]
|
||||
journey = jps.JourneyDescription(journey_stages)
|
||||
journey_id = self.simulation.add_journey(journey)
|
||||
|
||||
# Store door system
|
||||
self.door_systems[door_id] = {
|
||||
"waiting_area": waiting_area,
|
||||
"waiting_set_id": waiting_set_id,
|
||||
"queue_waypoints": queue_waypoints,
|
||||
"journey_id": journey_id,
|
||||
"door_polygon": door_polygon
|
||||
}
|
||||
|
||||
def _precompute_spawn_events(self) -> List[Dict]:
|
||||
"""Precompute all spawn events with positions and agent configurations."""
|
||||
events = []
|
||||
|
||||
# Group agents by their assigned group
|
||||
agents_by_group = {}
|
||||
for agent in self.all_agents:
|
||||
for group_name, group_info in self.config.groups.items():
|
||||
if agent.door == group_info["door"]:
|
||||
if group_name not in agents_by_group:
|
||||
agents_by_group[group_name] = []
|
||||
agents_by_group[group_name].append(agent)
|
||||
break
|
||||
|
||||
# Create events for each group
|
||||
for group_name, group_info in self.config.groups.items():
|
||||
door_id = group_info["door"]
|
||||
spawn_time = group_info["spawn_time"]
|
||||
group_agents = agents_by_group.get(group_name, [])
|
||||
|
||||
if not group_agents:
|
||||
continue
|
||||
|
||||
# Generate spawn positions
|
||||
door_polygon = self.config.door_polygons[door_id]
|
||||
spawn_positions = self._generate_spawn_points(
|
||||
door_polygon,
|
||||
len(group_agents)
|
||||
)
|
||||
|
||||
# Create events
|
||||
for agent, position in zip(group_agents, spawn_positions):
|
||||
events.append({
|
||||
"time": spawn_time,
|
||||
"agent_config": agent,
|
||||
"position": position,
|
||||
"group": group_name,
|
||||
"door": door_id
|
||||
})
|
||||
|
||||
# Sort events by time
|
||||
events.sort(key=lambda x: x["time"])
|
||||
return events
|
||||
|
||||
def _execute_simulation(self):
|
||||
"""Execute the simulation with dynamic spawning."""
|
||||
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()
|
||||
|
||||
# Process spawn events
|
||||
self._process_spawn_events(current_time, event_index, spawned_event_indices,
|
||||
agents_in_door_area)
|
||||
|
||||
# Update event index
|
||||
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
|
||||
|
||||
# Iterate simulation
|
||||
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_event_indices: set, agents_in_door_area: Dict):
|
||||
"""Process all spawn events that should occur at the current time."""
|
||||
while (event_index < len(self.spawn_events) and
|
||||
self.spawn_events[event_index]["time"] <= current_time and
|
||||
event_index not in spawned_event_indices):
|
||||
|
||||
event = self.spawn_events[event_index]
|
||||
door_id = event["door"]
|
||||
agent_config = event["agent_config"]
|
||||
|
||||
# Check door capacity
|
||||
if agents_in_door_area[door_id] < self.config.door_capacity:
|
||||
self._spawn_agent(event, door_id, agent_config)
|
||||
agents_in_door_area[door_id] += 1
|
||||
spawned_event_indices.add(event_index)
|
||||
|
||||
# Move to next event
|
||||
event_index += 1
|
||||
|
||||
def _spawn_agent(self, event: Dict, door_id: int, agent_config: AgentConfig):
|
||||
"""Spawn a single agent into the simulation."""
|
||||
journey_id = self.door_systems[door_id]["journey_id"]
|
||||
|
||||
agent_params = jps.CollisionFreeSpeedModelAgentParameters(
|
||||
position=event["position"],
|
||||
journey_id=journey_id,
|
||||
stage_id=self.door_systems[door_id]["waiting_set_id"],
|
||||
radius=agent_config.radius,
|
||||
v0=agent_config.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})")
|
||||
|
||||
|
||||
# Example usage function
|
||||
def create_and_run_simulation() -> PedestrianSimulation:
|
||||
"""
|
||||
Example function to create and run a complete simulation.
|
||||
|
||||
Returns:
|
||||
PedestrianSimulation: The completed simulation object
|
||||
"""
|
||||
# Define door polygons
|
||||
door_polygons = {
|
||||
1: shapely.Polygon([(5, 5), (10, 5), (10, 15), (5, 15)]),
|
||||
2: shapely.Polygon([(20, 5), (25, 5), (25, 15), (20, 15)]),
|
||||
3: shapely.Polygon([(35, 5), (40, 5), (40, 15), (35, 15)]),
|
||||
}
|
||||
|
||||
# Define groups (example with 4 groups, extend to 13 as needed)
|
||||
groups = {
|
||||
"group_1": {"door": 1, "spawn_time": 0.0, "size": 40},
|
||||
"group_2": {"door": 2, "spawn_time": 5.0, "size": 35},
|
||||
"group_3": {"door": 3, "spawn_time": 10.0, "size": 30},
|
||||
"group_4": {"door": 1, "spawn_time": 15.0, "size": 25},
|
||||
# Add 9 more groups to reach 13 total
|
||||
}
|
||||
|
||||
# Create simulation configuration
|
||||
config = SimulationConfig(
|
||||
door_polygons=door_polygons,
|
||||
groups=groups,
|
||||
total_simulation_time=200.0, # Adjust as needed
|
||||
door_capacity=10,
|
||||
min_spacing=0.6
|
||||
)
|
||||
|
||||
# Create and run simulation
|
||||
sim_runner = PedestrianSimulation(config)
|
||||
simulation = sim_runner.run()
|
||||
|
||||
return sim_runner
|
||||
|
||||
|
||||
# Quick execution function
|
||||
def run_simulation_quickstart():
|
||||
"""Quickstart function for running a basic simulation."""
|
||||
print("Pedestrian Simulation Quickstart")
|
||||
print("-" * 40)
|
||||
|
||||
# You can modify these parameters
|
||||
door_polygons = {
|
||||
1: shapely.Polygon([(2, 2), (6, 2), (6, 8), (2, 8)]),
|
||||
2: shapely.Polygon([(10, 2), (14, 2), (14, 8), (10, 8)]),
|
||||
3: shapely.Polygon([(18, 2), (22, 2), (22, 8), (18, 8)]),
|
||||
}
|
||||
|
||||
groups = {
|
||||
"class_a": {"door": 1, "spawn_time": 0.0, "size": 30},
|
||||
"class_b": {"door": 2, "spawn_time": 10.0, "size": 25},
|
||||
"class_c": {"door": 3, "spawn_time": 20.0, "size": 20},
|
||||
}
|
||||
|
||||
config = SimulationConfig(
|
||||
door_polygons=door_polygons,
|
||||
groups=groups,
|
||||
total_simulation_time=100.0,
|
||||
door_capacity=8
|
||||
)
|
||||
|
||||
sim = PedestrianSimulation(config)
|
||||
return sim.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Option 1: Use the example function
|
||||
# sim_runner = create_and_run_simulation()
|
||||
|
||||
# Option 2: Use quickstart for testing
|
||||
simulation = run_simulation_quickstart()
|
||||
|
||||
# You can now analyze the simulation results
|
||||
print(f"\nFinal simulation state:")
|
||||
print(f" Elapsed time: {simulation.elapsed_time():.2f}s")
|
||||
# Additional analysis can be added here
|
||||
17
archive/source/test/config.py
Normal file
17
archive/source/test/config.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
E.Drake - ENGN-2220
|
||||
|
||||
Thu Jan 22 23:48:50 2026
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).parent.parent.parent
|
||||
SOURCE_DIR = ROOT/"source"
|
||||
ARCHIVE_DIR = ROOT/"archive"
|
||||
PATH_DIR = ROOT/"path"
|
||||
AGENTS_DIR = ROOT/SOURCE_DIR/"sim_agents"
|
||||
GEO_DIR = ROOT/SOURCE_DIR/"sim_geometry"
|
||||
TEST_DIR = ROOT/SOURCE_DIR/"test"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user