|
3 | 3 |
|
4 | 4 | from enum import Enum |
5 | 5 |
|
6 | | -from pedpy.data.trajectory_data import TrajectoryData |
7 | | -from .method_utils import _compute_individual_distances |
8 | | -from pedpy.column_identifier import FRAME_COL, ID_COL, INTRUSION_COL |
| 6 | +import numpy as np |
9 | 7 | import pandas |
| 8 | +import shapely |
| 9 | + |
| 10 | +from pedpy.column_identifier import ( |
| 11 | + AVOIDANCE_COL, |
| 12 | + FRAME_COL, |
| 13 | + ID_COL, |
| 14 | + INTRUSION_COL, |
| 15 | +) |
| 16 | +from pedpy.data.trajectory_data import TrajectoryData |
| 17 | +from pedpy.methods.method_utils import ( |
| 18 | + SpeedCalculation, |
| 19 | + _compute_individual_distances, |
| 20 | +) |
| 21 | +from pedpy.methods.speed_calculator import compute_individual_speed |
10 | 22 |
|
11 | 23 |
|
12 | 24 | class IntrusionMethod(Enum): # pylint: disable=too-few-public-methods |
@@ -50,3 +62,93 @@ def compute_intrusion( |
50 | 62 | ) |
51 | 63 |
|
52 | 64 | return intrusion |
| 65 | + |
| 66 | + |
| 67 | +def compute_avoidance( |
| 68 | + *, |
| 69 | + traj_data: TrajectoryData, |
| 70 | + frame_step: int, |
| 71 | + radius: float = 0.2, |
| 72 | + tau_0: float, |
| 73 | +) -> pandas.DataFrame: |
| 74 | + """_summary_. |
| 75 | +
|
| 76 | + TODO add documentation here |
| 77 | +
|
| 78 | + Args: |
| 79 | + traj_data (TrajectoryData): _description_ |
| 80 | + frame_step (int): _description_ |
| 81 | + radius (float): _description_ |
| 82 | + tau_0 (float): _description_ |
| 83 | +
|
| 84 | + Returns: |
| 85 | + pandas.DataFrame: _description_ |
| 86 | + """ |
| 87 | + velocity = compute_individual_speed( |
| 88 | + traj_data=traj_data, |
| 89 | + frame_step=frame_step, |
| 90 | + compute_velocity=True, |
| 91 | + speed_calculation=SpeedCalculation.BORDER_SINGLE_SIDED, |
| 92 | + ) |
| 93 | + |
| 94 | + data = pandas.merge(traj_data.data, velocity, on=[ID_COL, FRAME_COL]) |
| 95 | + data["velocity"] = shapely.points(data.v_x, data.v_y) |
| 96 | + |
| 97 | + matrix = pandas.merge( |
| 98 | + data, data, how="outer", on=FRAME_COL, suffixes=("", "_neighbor") |
| 99 | + ) |
| 100 | + matrix = matrix[matrix.id != matrix.id_neighbor] |
| 101 | + |
| 102 | + distance = np.linalg.norm( |
| 103 | + shapely.get_coordinates(matrix.point) |
| 104 | + - shapely.get_coordinates(matrix.point_neighbor), |
| 105 | + axis=1, |
| 106 | + ) |
| 107 | + |
| 108 | + e_v = ( |
| 109 | + shapely.get_coordinates(matrix.point) |
| 110 | + - shapely.get_coordinates(matrix.point_neighbor) |
| 111 | + ) / distance[:, np.newaxis] |
| 112 | + |
| 113 | + v_rel = shapely.get_coordinates(matrix.velocity) - shapely.get_coordinates( |
| 114 | + matrix.velocity_neighbor |
| 115 | + ) / np.linalg.norm( |
| 116 | + shapely.get_coordinates(matrix.velocity) |
| 117 | + - shapely.get_coordinates(matrix.velocity_neighbor) |
| 118 | + ) |
| 119 | + |
| 120 | + v_rel_norm = np.linalg.norm(v_rel, axis=1) |
| 121 | + |
| 122 | + dot_product = np.sum( |
| 123 | + np.array(np.array(e_v.tolist())) * np.array(np.array(v_rel.tolist())), |
| 124 | + axis=1, |
| 125 | + ) |
| 126 | + |
| 127 | + cos_alpha = dot_product / (distance * v_rel_norm) |
| 128 | + |
| 129 | + ttc = np.full(matrix.shape[0], np.inf) |
| 130 | + |
| 131 | + capital_a = (cos_alpha**2 - 1) * distance**2 + radius**2 |
| 132 | + |
| 133 | + # (0.5 * l_a + 0.5 * l_b)**2 in paper |
| 134 | + sqrt_a_safe = np.where( |
| 135 | + capital_a >= 0, np.sqrt(np.where(capital_a >= 0, capital_a, 0)), np.nan |
| 136 | + ) |
| 137 | + |
| 138 | + valid_conditions = ( |
| 139 | + (capital_a >= 0) |
| 140 | + & (-cos_alpha * distance - sqrt_a_safe >= 0) |
| 141 | + & (v_rel_norm != 0) |
| 142 | + ) |
| 143 | + |
| 144 | + ttc[valid_conditions] = ( |
| 145 | + -cos_alpha[valid_conditions] * distance[valid_conditions] |
| 146 | + - np.sqrt(capital_a[valid_conditions]) |
| 147 | + ) / v_rel_norm[valid_conditions] |
| 148 | + |
| 149 | + matrix[AVOIDANCE_COL] = tau_0 / ttc |
| 150 | + |
| 151 | + avoidance = matrix.groupby(by=[ID_COL, FRAME_COL], as_index=False).agg( |
| 152 | + avoidance=(AVOIDANCE_COL, "max") |
| 153 | + ) |
| 154 | + return avoidance |
0 commit comments