로봇공학기초
[로봇공학기초 / 2DOF] #3. Work Space (작업공간)
jhpark0518
2025. 3. 31. 10:00
🦾 작업공간(Workspace)이란?
로봇팔이 실제로 움직일 수 있는 공간.
즉, 말단(End-effector)이 도달할 수 있는 위치의 전체 집합을 우리는 작업공간 (Workspace) 이라고 부릅니다.
“ 아무리 열심히 움직여도, 절대 닿지 않는 곳이 있다면? ”
그건 작업공간 밖입니다.
그럼, 이 작업공간은 수치적으로 어떻게 표현할 수 있을까요?
✍ 수치적으로 풀기
2자유도 로봇팔에서, 각 관절의 회전 범위가 $360^\circ$라고 가정하면, 말단 위치 $(x, y)$는 다음 조건을 만족해야 합니다:
- 최대 도달 거리: $L_1 + L_2$
- 최소 도달 거리: $|L_1 - L_2|$
즉, 작업공간은 아래 조건을 만족하는 원판 형태입니다:
$$
|L_1 - L_2| \leq \sqrt{x^2 + y^2} \leq L_1 + L_2
$$
이 조건을 만족하지 않으면, 해당 위치에는 로봇팔이 절대 도달할 수 없습니다.
📈 그래프로 그리기
- 바깥 검정 띠: 최대 도달 거리 $L_1 + L_2$
- 안쪽 검정 띠: 최소 도달 거리 $|L_1 - L_2|$
- 그 사이의 회색 원판 영역: 로봇팔이 실제로 움직일 수 있는 작업 공간입니다.
- 빨간 마커: 목표점(1번: 외곽, 2번: 중간, 3번: 내곽)
💬 부가 설명
대부분의 경우 작업공간은 단순한 원판처럼 보이지만,
장애물, 관절 제한, 혹은 로봇의 구조적 특성에 따라 훨씬 복잡한 형태가 되기도 합니다.
💻 아래는 그래프를 그릴 때 사용한 Python 코드입니다.
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'Malgun Gothic'
plt.rcParams['axes.unicode_minus'] = False
# 링크 길이
L1, L2 = 1, 0.5
# 목표점 목록
targets = {
"1번 (외곽)": (0, L1 + L2),
"2번 (중간)": (-1.0, 1.0),
"3번 (내곽)": (abs(L1 - L2), 0),
}
marker = ['D', 'o', 's']
# 시각화
fig, ax = plt.subplots(figsize=(6, 6), dpi=300)
ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)
ax.set_aspect('equal')
ax.set_title("2자유도 로봇팔 작업공간 + 각 목표점 로봇팔")
ax.set_axisbelow(True)
plt.grid(True)
# 작업공간 영역
outer_fill = plt.Circle((0, 0), L1 + L2, color='#999999', alpha=0.2, zorder=1)
inner_fill = plt.Circle((0, 0), abs(L1 - L2), color='white', zorder=2)
outer_edge = plt.Circle((0, 0), L1 + L2, color='black', fill=False, linewidth=1.5, zorder=3)
inner_edge = plt.Circle((0, 0), abs(L1 - L2), color='black', fill=False, linewidth=1.5, zorder=4)
ax.add_patch(outer_fill)
ax.add_patch(inner_fill)
ax.add_patch(outer_edge)
ax.add_patch(inner_edge)
# 각 목표점에 대해: 역기구학 → 로봇팔 그림
for (label, (xt, yt)), marker in zip(targets.items(), marker):
# 거리 계산
r = np.hypot(xt, yt)
# 역기구학 (Cosine Law)
cos_theta2 = (r**2 - L1**2 - L2**2) / (2 * L1 * L2)
if abs(cos_theta2) > 1:
print(f"{label}은 작업공간 밖입니다.")
continue
theta2 = np.arccos(cos_theta2) # Elbow-down 기준
k1 = L1 + L2 * np.cos(theta2)
k2 = L2 * np.sin(theta2)
theta1 = np.arctan2(yt, xt) - np.arctan2(k2, k1)
# Forward Kinematics
x0, y0 = 0, 0
x1 = x0 + L1 * np.cos(theta1)
y1 = y0 + L1 * np.sin(theta1)
x2 = x1 + L2 * np.cos(theta1 + theta2)
y2 = y1 + L2 * np.sin(theta1 + theta2)
# 로봇팔 그리기
ax.plot([x0, x1], [y0, y1], 'b', linewidth=3, zorder=6)
ax.plot([x1, x2], [y1, y2], 'g', linewidth=5, zorder=6)
ax.plot(x0, y0, 'ko', markersize=7, zorder=7) # 베이스
ax.plot(x1, y1, 'ko', markersize=7, zorder=7) # 관절
# 목표점 표시
ax.plot(xt, yt, marker = marker, color = 'red', label=label, markersize=7, zorder=8)
# 라벨
plt.xlabel("X")
plt.ylabel("Y")
plt.legend()
plt.show()
🔧 실행 환경
- Python 3.8 이상
- matplotlib
- numpy
- Jupyter Notebook (추천)
📘 다음 편 예고
다음 글에서는, 이 작업공간 안에서 속도와 힘의 방향을 정의하는 Jacobian(자코비안) 행렬에 대해 알아보겠습니다.