

import numpy as np
import matplotlib.pyplot as plt
# 격자 기반 지도의 크기 설정, 여기서는 10 x 10 격자 사용
grid_size = 10
# 0으로 초기화된 10x10 격자를 생성, 0은 비점유 셀을 나타냄
grid_map = np.zeros((grid_size, grid_size))
# 장애물을 나타내기 위해 일부 셀을 1로 설정, 1은 점유 셀을 나타냄
# 예시로, 격자의 가운데에 작은 장애물을 생성
obstacle_positions = [(4,4), (4,5), (5,4), (5,5)] #장애물의 위치를 표시하기 위한 좌표를 정의, 격자의 중심에 작은 장애물을 생성하기 위해 중심 주변의 4개의 셀을 장애물로 설정
for pos in obstacle_positions:
grid_map[pos] = 1 #장애물 위치에 해당하는 셀을 1로 설정하여 격자 맵에 장애물을 추가
# 격자 기반 지도를 시각화
plt.imshow(grid_map, cmap='Greys', interpolation='none') #cmap 에서 색상 맵을 흑백으로 설정, 0은 흰색으로 1은 흑백으로 그림
plt.title('Grid-based Map Representation')
plt.xticks(range(grid_size))
plt.yticks(range(grid_size))
plt.grid(which = 'both') # 격자 그림
plt.show()
코드를 살펴보면
지도의 크기를 설정한다.
grid_size = 10
지도의 각 셀 상태를 저장: 0은 비점유 셀, 1은 점유 셀
grid_map = np.zeros((grid_size, grid_size))
장애물의 위치를 정의하고 해당 위치의 셀값을 1로 설정
obstacle_positions = [(4,4), (4,5), (5,4), (5,5)]
for pos in obstacle_positions:
grid_map[pos] = 1






-> 분류된 셀을 기반으로 인접 그래프를 생성
-> 간의 인접 관계를 노드와 엣지로 표현하며, 각 노드는 자유 공간 셀을 대표하고, 엣지는 노드(셀)간의 이동 가능성을 나타냄
-> 그래프 생성 과정에서 중요한 위치(예: 셀의 꼭짓점, 셀 간의 경계)에서 노드를 추출하고, 이동 가능한 셀 간에 엣지를 생성하여 연결성을 표현




import matplotlib.pyplot as plt
from shapely.geometry import LineString, Point, Polygon # Python의 Shapely 라이브러리에 포함된 모듈로 평면 기하학(2D geometry)을 조작하고 분석할 수 있는 기능
from itertools import combinations
def is_visible(p1, p2, obstacles):
"""
두 점 p1,p2 가 주어진 장애물에 의해 가려지지 않고, 장애물 내부를 통과하지 않는지 확인
"""
line = LineString([p1, p2]) # 선분 생성, 두 점 p1, p2를 연결하는 LineString 객체를 생성
for obs in obstacles: #장애물과의 교차 확인: 입력으로 받은 모든 장애물 obstacles에 대해 반복문을 수행
if line.crosses(obs) or obs.contains(line): # 1) line.crosses(obs): line이 obs라는 장애물과 교차하는지 확인, 장애물을 교차한다는 것은 선분이 장애물의 경계선을 건너는 것을 의미
return False # 2) obs.contains(line) : 선분 line이 장애물 obs 내부에 완전히 포함되는지 확인, 이 경우에도 두 점사이의 경로가 장애물에 의해 차단
return True
def create_visibility_graph(vertices, obstacles):
"""
주어진 꼭짓점과 장애물을 기반으로 가시성 그래프를 생성
"""
edges = [] # 에지 리스트 초기화
for p1, p2 in combinations(vertices, 2): # 모든 꼭짓점 쌍에 대한 반복, combinations(vertices, 2)는 주어진 vertices 리스트에서 모두 가능한 두 점의 조합을 생성, 이는 각 꼭짓점 쌍 (p1,p2) 에 대해 반복문을 수행
if is_visible(p1, p2, obstacles): # 가시성 확인 : 각 꼭짓점 쌍에 대해 is_visible 함수를 호출, 이 함수는 두 점 p1, p2 사이에 직선 경로가 장애물에 의해 차단되지 않는지를 결정
edges.append([p1,p2]) # 에지 추가 : 만약 is_visible 함수가 True를 반환하면, (p1 ,p2)쌍은 서로 볼 수 있다는 의미이므로, 이 쌍을 edges 리스트에 추가
return edges
def plot_graph(vertices, edges, obstacles):
"""
가시성 그래프의 장애물을 시각화함.
"""
plt.figure() # 그래프 창 초기화: plt.figure()를 호출하면 새로운 그래프 창을 생성,
ax = plt.gca() # plt.gca() 를 사용하여 현재 활성화된 축(Axis)를 호출
#장애물 플롯
for obs in obstacles: # 장애물 시각화 : obstacles 리스트에 있는 각 장애물 obs에 대해 반복
x, y = obs.exterior.xy #obs.exterior.xy를 호출하여 장애물의 외곽선을 구성하는 x좌표와 y좌표를 획득
ax.fill(x, y, alpha = 0.5, fc = 'r', ec = 'black') # ax.fill 메서드를 사용하여 이 좌표들로 정의된 장애물의 영역을 채우서 그림
# 여기서 alpha는 채우기 색상의 투명도, fc는 채우기 색상을, ec는 외곽선 색상을 지정
# 가시성 그래프 플롯
for edge in edges: # 가시성 그래프 시각화 : 생성된 에지(연결선) 리스트 edges를 반복하여 각 에지에 대해 두 점 p1과 p2 사이에 선을 도시
p1, p2 = edge
plt.plot([p1.x, p2.x], [p1.y, p2.y], 'go-', markersize = 5) #plt.plot 함수를 사용하여 이 선들을 그래프에 추가
# 여기서 점들은 녹색 원으로 표시('-go'), 마커 크기는 5로 설정
plt.axis('equal') # 축 비율 설정 : plt.axis('equal')은 x축과 y축의 스케일을 동일하게 만들어 그림의 비율을 1:1로 설정
plt.show() # 그래프 표새 : 마지막으로 plt.show()를 호출하여 준비된 그래프 점을 사용자에게 표시
#장애물 정의
obstacles = [Polygon([(2,2), (2,3), (3,5), (4,4), (4,2)]),
Polygon([(6,8), (8,8), (8,6)]),
Polygon([(10,2), (10,4), (12,5), (12,3)])]
#모든 꼭짓점 정의
vertices = [Point(x,y) for obs in obstacles for x,y in obs.exterior.coords[:-1]]
"""
obs.exterior.coords : Polygon 객체 obs의 외곽선을 나태는 좌표를 가져옴, coords는 해당 외곽선을 구성하는 (x,y)쌍의 시퀀스
for x,y in obs.exterior.coords[:-1] : 이 내부 루프는 각 Polygon 의 외곽선 좌표를 반복하고 각 좌표 쌍 (x,y)를 추출
"""
# 가시성 그래프 생성
edges = create_visibility_graph(vertices, obstacles)
# 그래프 시각화
plot_graph(vertices, edges, obstacles)


import numpy as np
import matplotlib.pyplot as plt
#환경 설정
goal = np.array([8, 8]) # 로봇이 이동하고자 하는 목표 지점의 좌표를 나타내는 numpy 배열
obstacles = [np.array([3,3]), np.array([5,5])] # 장애물 위치를 나타내는 numpy 배열 리스트
start = np.array([1,1]) #로봇의 시작 위치를 나타내는 numpy 배열
# 매개변수 설정
attractive_scale = 1.0 # 목표 지점에 대한 인력의 크기를 제어하는 스케일 매개변수
repulsive_scale = 5.0 # 장애물로부터의 반발력의 크기를 제어하는 스케일 매개변수
repulsive_threshold = 10.0 # 반발력이 적용되는 최대 거리, 이 거리 이내에 있는 장애물은 로봇에 대한 반발력을 발생
# 그리드 설정
x = np.linspace(0, 10, 100) # x와 y는 그리드의 x 및 y 좌표를 나타내는 numpy 배열
y = np.linspace(0, 10, 100)
X, Y = np.meshgrid(x,y) # X와 Y는 그리드의 x 및 y 좌표를 포함하는 2차원 배열
def calculate_potential_field(x, y):
# 로봇이 목표 지점으로 이동하려는 인력 필드를 계산. 목표 지점까지의 거리에 따라 인력이 증가
attractive_potential = 0.5 * attractive_scale * np.sqrt((x - goal[0])**2 + (y - goal[1])**2)
# 장애물로부터의 반발력 필드를 계산, 장애물과의 거리가 repulsive_threshold보다 작을 때, 반발력이 적용
repulsive_potential = 0
for obs in obstacles:
dist_to_obs = np.sqrt((x - obs[0])**2 + (y - obs[1])**2 )
if dist_to_obs <= repulsive_threshold:
repulsive_potential += 0.5 * repulsive_scale * (1 - dist_to_obs / repulsive_threshold)
#총 포텐셜 계산
total_potential = attractive_potential + repulsive_potential
return total_potential, attractive_potential, repulsive_potential
# calculate_potential_field 함수를 그리드의 각 점에 적용하여 포텐셜 필드를 계산
PF, AP, RP = np.vectorize(calculate_potential_field)(X,Y)
# 결과 시각화
plt.figure(figsize=(8,6))
contour = plt.contourf(X, Y, PF, levels = 50, cmap = 'viridis') # 계산된 포텐셜 필드를 등고선 그래프로 시각화
plt.colorbar(contour)
plt.plot(goal[0], goal[1], 'r*', markersize = 15, label = 'Goal') # 목표 지점을 빨간 별로 표시
plt.plot(start[0], start[1], 'bs', markersize = 10, label = 'Start') # 시작 위치를 파란 사각형으로 표시
for obs in obstacles:
plt.plot(obs[0], obs[1], 'ko', markersize = 10, label = 'Obstalces') # 장애물 위치를 검은색 원으로 표시
plt.legend()
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Artificial Potential Field')
plt.show()
