Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fast marching #390

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
367 changes: 367 additions & 0 deletions notebooks/Fast-Marching.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,367 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import pathlib\n",
"import warnings\n",
"\n",
"import numpy as np\n",
"import pandas as pd\n",
"import shapely\n",
"\n",
"warnings.filterwarnings(\"ignore\")"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from pedpy import WalkableArea\n",
"\n",
"walkable_area = WalkableArea(\n",
" # complete area\n",
" [\n",
" (3.5, -2),\n",
" (3.5, 8),\n",
" (-3.5, 8),\n",
" (-3.5, -2),\n",
" ],\n",
" obstacles=[\n",
" # left barrier\n",
" [\n",
" (-0.7, -1.1),\n",
" (-0.25, -1.1),\n",
" (-0.25, -0.15),\n",
" (-0.4, 0.0),\n",
" (-2.8, 0.0),\n",
" (-2.8, 6.7),\n",
" (-3.05, 6.7),\n",
" (-3.05, -0.3),\n",
" (-0.7, -0.3),\n",
" (-0.7, -1.0),\n",
" ],\n",
" # right barrier\n",
" [\n",
" (0.25, -1.1),\n",
" (0.7, -1.1),\n",
" (0.7, -0.3),\n",
" (3.05, -0.3),\n",
" (3.05, 6.7),\n",
" (2.8, 6.7),\n",
" (2.8, 0.0),\n",
" (0.4, 0.0),\n",
" (0.25, -0.15),\n",
" (0.25, -1.1),\n",
" ],\n",
" ],\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"\n",
"from pedpy import plot_walkable_area\n",
"\n",
"plot_walkable_area(walkable_area=walkable_area).set_aspect(\"equal\")\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"from pedpy import MeasurementArea\n",
"\n",
"measurement_area = MeasurementArea(\n",
" [(-0.4, 0.5), (0.4, 0.5), (0.4, 1.3), (-0.4, 1.3)]\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"\n",
"from pedpy import plot_measurement_setup\n",
"\n",
"plot_measurement_setup(\n",
" walkable_area=walkable_area,\n",
" measurement_areas=[measurement_area],\n",
" ma_line_width=2,\n",
" ma_alpha=0.2,\n",
").set_aspect(\"equal\")\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pedpy import TrajectoryData, load_trajectory, plot_trajectories\n",
"from pedpy.column_identifier import FRAME_COL\n",
"\n",
"traj_total = load_trajectory(\n",
" trajectory_file=pathlib.Path(\"demo-data/bottleneck/040_c_56_h-.txt\")\n",
")\n",
"min_frame = 300\n",
"max_frame = 310\n",
"\n",
"traj_cut = TrajectoryData(\n",
" data=traj_total.data[\n",
" (traj_total.data[FRAME_COL] > min_frame)\n",
" & (traj_total.data[FRAME_COL] < max_frame)\n",
" ],\n",
" frame_rate=traj_total.frame_rate,\n",
")\n",
"\n",
"plot_trajectories(\n",
" traj=traj_cut, traj_alpha=0.5, traj_width=1, walkable_area=walkable_area\n",
").set_aspect(\"equal\")\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The Fast-Marching-Method is a way to compute the propagation of wavefronts. In this Notebook it is explained how to use this method to compute individual area for pedestrian.\n",
"\n",
"The Fast-Marching-Method discretizes the room into squares of equal size and computes the propagation of wavefronts on this grid.\n",
"For each pedestrian a wavefront is started at the same time. All the grid-cells that the wavefront reaches will be added to the individual area. The Propagation of the wavefront stops if it reaches a cell that has already been assigned to another person, a cell that is outside the walkable area, or the Cutoff-radius is extended. In this way, individual areas can be created that are similar to the Voronoi cells, but take into account the walkable area.\n",
"\n",
"There are two main steps to computing the individual areas with the Fast-Marching-Method:\n",
"\n",
"At first you need to create a DataFrame containing information about the Shape and the Speedmap.\n",
"The shape of each pedestrian is transferred to the grid and is the starting position for the wavefront associated with it.\n",
"\n",
"The Speedmap is an array which specifies the propagation speed of the wavefront.\n",
"\n",
"The GridInfo-object saves data related to the grid. this includes the walkable_area as well as the size of the grid-cells.\n",
"\n",
"It is possible to compute the DataFrame on your own, but you can also use the compute_shape_and_speedmap function.\n",
"This function will take the trajectory information, information about the Grid and additional information required to compute the shape and speedmap.\n",
"additionaly you need to specify a lambda-function used to create the shape and a lambda-function to create the speedmap.\n",
"\n",
"At first the shape of the Pedestrian is specified as the point of his location from the trajectory. \n",
"The Speedmap will be computed with the default parameter of the function compute_speedmap.\n",
"\n",
"These lambda-function receive the trajectories, information about the cell size and additional information. \n",
"Here no additional information is needed for the computation."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pedpy.methods.method_utils import (\n",
" GridInfo,\n",
" apply_computed_speedmap,\n",
" apply_point_as_shape,\n",
" compute_shape_and_speedmap,\n",
")\n",
"\n",
"grid = GridInfo(walkable_area=walkable_area, cell_size=0.05)\n",
"\n",
"shape_and_speedmap = compute_shape_and_speedmap(\n",
" traj=traj_cut,\n",
" grid=grid,\n",
" calc_shape_from_frame=apply_point_as_shape,\n",
" calc_speedmap_from_frame=apply_computed_speedmap,\n",
" additions=None,\n",
")\n",
"\n",
"print(\n",
" f\"columns in shape and speedmap dataframe: {list(shape_and_speedmap.columns)}\"\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"With the shape_and_speedmap DataFrame it is possible to compute the individual areas with the Fast-Marching-Method.\n",
"\n",
"The result is similar the the result of compute_individual_voronoi_cells and includes the columns id, frame, polygon, density.\n",
"Thus the results can be used the same way you can use individual voronoi cells."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pedpy.methods.method_utils import compute_individual_areas\n",
"\n",
"individual_areas = compute_individual_areas(\n",
" shape_and_speedmap=shape_and_speedmap, grid=grid, cutoff_distance=1.5\n",
")\n",
"\n",
"print(individual_areas)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Below is a plot with the created individual areas of frame 305. The result are similar to the Voronoi-Cells. However you can see how the wavefront of the person leaving the bottleneck propagate around the non-walkable-area taking into account where a person can walk and where there are obstacles in the way. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"\n",
"from pedpy import DENSITY_COL, plot_voronoi_cells\n",
"\n",
"plot_voronoi_cells(\n",
" voronoi_data=individual_areas,\n",
" traj_data=traj_cut,\n",
" frame=305,\n",
" walkable_area=walkable_area,\n",
" color_by_column=DENSITY_COL,\n",
" vmin=0,\n",
" vmax=10,\n",
").set_aspect(\"equal\")\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, the shape of the pedestrian should not be specified by a point, but by the approximation of the body ellipse of the GCFM.\n",
"\n",
"To do this you can use the compute_shape_and_speedmap together with the lambda-function apply_ellipses_as_shape.\n",
"the additional DataFrame has to include the information about velocity in x and y direction as well as the speed of the pedestrian.\n",
"These information can be computed by using the compute_individual_speed function with the option compute_velocity=True.\n",
"Additionally parameters for the Ellipse of the GCFM can be specified. Otherwise the default parameters of GCFM are used.\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"from pedpy import SpeedCalculation, compute_individual_speed\n",
"from pedpy.column_identifier import (\n",
" FRAME_COL,\n",
" ID_COL,\n",
" SPEED_COL,\n",
" V_X_COL,\n",
" V_Y_COL,\n",
")\n",
"from pedpy.methods.method_utils import (\n",
" GridInfo,\n",
" apply_computed_speedmap,\n",
" apply_ellipses_as_shape,\n",
" compute_shape_and_speedmap,\n",
")\n",
"\n",
"grid = GridInfo(walkable_area=walkable_area, cell_size=0.05)\n",
"\n",
"individual_speed = compute_individual_speed(\n",
" traj_data=traj_total,\n",
" frame_step=10,\n",
" compute_velocity=True,\n",
" speed_calculation=SpeedCalculation.BORDER_SINGLE_SIDED,\n",
")\n",
"additions = individual_speed[[ID_COL, FRAME_COL, SPEED_COL, V_X_COL, V_Y_COL]]\n",
"\n",
"additions[\"a_v\"] = 0.5\n",
"additions[\"a_min\"] = 0.1\n",
"additions[\"b_min\"] = 0.1\n",
"additions[\"b_max\"] = 0.2\n",
"\n",
"shape_and_speedmap = compute_shape_and_speedmap(\n",
" traj=traj_cut,\n",
" grid=grid,\n",
" calc_shape_from_frame=apply_ellipses_as_shape,\n",
" calc_speedmap_from_frame=apply_computed_speedmap,\n",
" additions=additions,\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"individual_areas = compute_individual_areas(\n",
" shape_and_speedmap=shape_and_speedmap, grid=grid, cutoff_distance=1.5\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plot_voronoi_cells(\n",
" voronoi_data=individual_areas,\n",
" traj_data=traj_cut,\n",
" frame=305,\n",
" walkable_area=walkable_area,\n",
" color_by_column=DENSITY_COL,\n",
" vmin=0,\n",
" vmax=10,\n",
").set_aspect(\"equal\")\n",
"\n",
"# Here the shape is plotted by plot_voronoi_cells however this is not compatible with Multipolygons.\n",
"shape_and_speedmap[\"polygon\"] = shape_and_speedmap[\"shape\"]\n",
"plot_voronoi_cells(voronoi_data=shape_and_speedmap, frame=305).set_aspect(\n",
" \"equal\"\n",
")\n",
"\n",
"plt.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv-3-11",
"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.11.0rc1"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Loading
Loading