def _generate_grid_map(self, local_lidar_xy_grid: np.ndarray) -> np.ndarray:
""" grid cell을, unknown(-1), empty(0), occupied(1)로 업데이트합니다."""
grid_map = np.full((self.grid_size, self.grid_size),
UNKNOWN,
dtype=int) # -1 is unknown
# Update empty cells (bresenham line) for each valid point
for x, y in local_lidar_xy_grid:
self.update_empty_cells(x, y, grid_map)
# Update grid map with occupied points
grid_map[local_lidar_xy_grid[:, 0], local_lidar_xy_grid[:, 1]] = OCCUPIED
return grid_map
def update_empty_cells(self, a_global_pcl_x_grid: int,
a_global_pcl_y_grid: int, grid_map: np.ndarray
) -> None:
grid_origin_x = grid_origin_y = self.grid_center
line_points = self.bresenham_line(grid_origin_x, grid_origin_y,
a_global_pcl_x_grid,
a_global_pcl_y_grid)
line_points = np.array(
line_points[:-1]) # Exclude the last point (occupied)
# Filter points that are within the grid bounds
valid_points = (line_points[:, 0] >= 0) & (
line_points[:, 0] < self.grid_size) & \
(line_points[:, 1] >= 0) & (
line_points[:, 1] < self.grid_size)
# Apply the filter
valid_line_points = line_points[valid_points]
# Update the grid using advanced indexing
grid_map[valid_line_points[:, 0],
valid_line_points[:, 1]] = FREE # Set to empty
grid_map
의 메모리 관리와 함수 호출 간의 메모리 사용에 초점을 맞춰 설명하겠습니다.= 파이썬에서 변수와 객체는 각각 다른 메모리 영역에 저장됩니다.
스택(Stack):
함수의 지역 변수
와 함수의 실행 상태(예: 반환 주소 등)
가 스택에 저장update_empty_cells
함수의 파라미터 a_global_pcl_x_grid
, a_global_pcl_y_grid
, grid_map
는 함수 호출 시 스택에 저장힙(Heap):
grid_map
과 같은 numpy 배열은 힙에 저장 파이썬에서는 명시적인 소유권 개념이 없으며, 대신 참조(reference)와 참조 카운트를 사용합니다.
참조:
grid_map
은 numpy 배열 객체이며, 이 객체는 힙에 저장grid_map
변수를 다른 함수에 인자로 넘기면, 그 함수에서도 동일한 객체를 참조
하게 됩니다.grid_map
을 update_empty_cells
함수의 인자로 넘길 때, 새로운 복사본이 생성되지 않고 동일한 객체에 대한 참조가 전달def _generate_grid_map(self, local_lidar_xy_grid: np.ndarray) -> np.ndarray:
""" grid cell을, unknown(-1), empty(0), occupied(1)로 업데이트합니다."""
grid_map = np.full((self.grid_size, self.grid_size), UNKNOWN, dtype=int) # -1 is unknown
# grid_map은 힙에 저장되고, 이 객체에 대한 참조는 스택에 저장됩니다.
# Update empty cells (bresenham line) for each valid point
for x, y in local_lidar_xy_grid:
self.update_empty_cells(x, y, grid_map)
# 각 호출에서 grid_map은 동일한 힙 객체를 참조합니다.
# Update grid map with occupied points
grid_map[local_lidar_xy_grid[:, 0], local_lidar_xy_grid[:, 1]] = OCCUPIED
return grid_map
grid_map
은 numpy 배열로 힙에 저장되며, 함수 호출 시 스택에 있는 변수 grid_map
이 이 객체를 참조update_empty_cells
함수로 grid_map
을 전달할 때도 동일한 힙 객체를 참조하게 됩니다.update_empty_cells
함수 내에서 grid_map
을 수정하면, 그 수정 내용은 _generate_grid_map
함수에서도 반영def update_empty_cells(self, a_global_pcl_x_grid: int, a_global_pcl_y_grid: int, grid_map: np.ndarray) -> None:
grid_origin_x = grid_origin_y = self.grid_center
line_points = self.bresenham_line(grid_origin_x, grid_origin_y, a_global_pcl_x_grid, a_global_pcl_y_grid)
line_points = np.array(line_points[:-1]) # Exclude the last point (occupied)
# Filter points that are within the grid bounds
valid_points = (line_points[:, 0] >= 0) & (line_points[:, 0] < self.grid_size) & \
(line_points[:, 1] >= 0) & (line_points[:, 1] < self.grid_size)
# Apply the filter
valid_line_points = line_points[valid_points]
# Update the grid using advanced indexing
grid_map[valid_line_points[:, 0], valid_line_points[:, 1]] = FREE # Set to empty
grid_map
은 동일한 힙 객체를 참조하고 있으므로, update_empty_cells
함수 내에서 grid_map
을 수정하면 해당 수정이 원본 grid_map
에 반영됩니다.