개요
**IK (Inverse Kinematics, 역기구학)**는 로봇 공학에서 가장 핵심적인 개념 중 하나입니다. 로봇 팔이 특정 위치의 물체를 잡으려면, 각 관절을 몇 도씩 회전해야 하는지 계산해야 합니다. 이 "목표 위치 → 관절 각도" 역방향 계산이 바로 역기구학입니다.
핵심 요약: FK는 "관절 각도 → 끝점 위치"를 구하고, IK는 "끝점 위치 → 관절 각도"를 구한다.
FK vs IK 비교
**정기구학(FK, Forward Kinematics)**과 **역기구학(IK, Inverse Kinematics)**은 서로 반대 방향의 문제를 풀고 있습니다.
| 구분 | FK (정기구학) | IK (역기구학) |
|---|---|---|
| 입력 | 각 관절 각도 | 엔드 이펙터 목표 위치/자세 |
| 출력 | 엔드 이펙터 위치/자세 | 각 관절 각도 |
| 해의 개수 | 항상 유일한 해 | 0개, 1개, 또는 다수 |
| 계산 난이도 | 비교적 간단 (행렬 곱) | 복잡 (비선형 방정식) |
| 사용 예 | 현재 로봇 자세 시각화 | 로봇 모션 플래닝, 물체 파지 |
flowchart LR
subgraph FK["정기구학 (FK)"]
A["관절 각도<br/>θ₁, θ₂, ..., θₙ"] -->|변환 행렬 곱| B["엔드 이펙터<br/>위치/자세 (x,y,z,R)"]
end
subgraph IK["역기구학 (IK)"]
C["엔드 이펙터<br/>목표 위치/자세"] -->|역계산| D["관절 각도<br/>θ₁, θ₂, ..., θₙ"]
end
B -.->|"역방향 문제"| C수학적 배경
FK는 각 관절의 **변환 행렬(Transformation Matrix)**을 순서대로 곱하여 엔드 이펙터의 위치를 구합니다.
여기서 은 관절 에서 관절 로의 **동차 변환 행렬(Homogeneous Transformation Matrix)**입니다.
2개의 링크를 가진 평면 로봇 팔의 경우, FK로 엔드 이펙터 위치를 구하면:
반대로 IK는 목표 좌표 로부터 , 를 구합니다:
포인트: 의 부호에서 알 수 있듯이, 같은 목표 위치에 대해 **"팔꿈치 위(elbow-up)"**와 "팔꿈치 아래(elbow-down)" 두 가지 해가 존재합니다.
flowchart TD
TARGET["목표 좌표 (x, y)"] --> COSQ2["cos θ₂ 계산"]
COSQ2 --> CHECK{"|cos θ₂| ≤ 1?"}
CHECK -->|No| NOANSWER["해 없음<br/>(도달 불가)"]
CHECK -->|Yes| THETA2["θ₂ = atan2(±√(1-cos²θ₂), cos θ₂)"]
THETA2 --> ELBOW_UP["해 1: Elbow-Up (+)"]
THETA2 --> ELBOW_DOWN["해 2: Elbow-Down (-)"]
ELBOW_UP --> THETA1_1["θ₁ 계산"]
ELBOW_DOWN --> THETA1_2["θ₁ 계산"]IK 풀이 방법
IK를 풀기 위한 방법은 크게 해석적 방법과 수치적 방법 두 가지로 나뉩니다.
수학 공식을 이용해 정확한 해를 직접 계산합니다.
- 장점: 빠르고 정확함, 모든 해를 한 번에 구할 수 있음
- 단점: 복잡한 로봇(6-DOF 이상)에서는 공식 유도가 매우 어려움
- 적용: 2-DOF, 3-DOF 등 단순한 구조, 또는 특수 구조(구형 손목 등)
**반복 계산(iteration)**으로 해에 점진적으로 접근합니다.
- 장점: 임의의 복잡한 로봇에 적용 가능
- 단점: 수렴 보장이 없을 수 있고, 하나의 해만 구함
- 대표 알고리즘:
| 알고리즘 | 특징 |
|---|---|
| Jacobian Transpose | 간단하지만 수렴 느림 |
| Jacobian Pseudo-Inverse | 가장 널리 사용, 특이점 근처 불안정 |
| Damped Least Squares (DLS) | 특이점 안정성 확보, 댐핑 계수 튜닝 필요 |
| CCD (Cyclic Coordinate Descent) | 게임/애니메이션에서 인기, 구현 간단 |
| FABRIK | 위치 기반, 빠르고 직관적 |
flowchart TD
START["IK 풀이 방법 선택"] --> Q1{"로봇 구조가<br/>단순한가?"}
Q1 -->|Yes| ANALYTICAL["해석적 방법<br/>(Analytical)"]
Q1 -->|No| Q2{"실시간 성능<br/>필요?"}
Q2 -->|Yes| CCD_FABRIK["CCD / FABRIK"]
Q2 -->|No| JACOBIAN["Jacobian 기반<br/>(Pseudo-Inverse, DLS)"]
ANALYTICAL --> RESULT["정확한 다중 해"]
CCD_FABRIK --> RESULT2["빠른 근사 해"]
JACOBIAN --> RESULT3["수렴된 수치 해"]코드 예시: 2-Link IK (Python)
아래는 2-Link 평면 로봇 팔의 IK를 Python으로 구현한 예시입니다.
import numpy as np
import matplotlib.pyplot as plt
def inverse_kinematics_2link(x: float, y: float, l1: float, l2: float):
"""2-Link 평면 로봇 팔의 역기구학 계산"""
# 목표 거리 계산
dist = x**2 + y**2
# cos(θ₂) 계산 — 코사인 법칙 활용
cos_theta2 = (dist - l1**2 - l2**2) / (2 * l1 * l2)
# 도달 가능 여부 확인
if abs(cos_theta2) > 1.0:
raise ValueError(f"목표 ({x}, {y})은 도달 불가능합니다.")
# θ₂: elbow-up, elbow-down 두 가지 해
sin_theta2_pos = np.sqrt(1 - cos_theta2**2) # elbow-up
sin_theta2_neg = -sin_theta2_pos # elbow-down
solutions = []
for sin_theta2 in [sin_theta2_pos, sin_theta2_neg]:
theta2 = np.arctan2(sin_theta2, cos_theta2)
theta1 = np.arctan2(y, x) - np.arctan2(
l2 * sin_theta2, l1 + l2 * cos_theta2
)
solutions.append((np.degrees(theta1), np.degrees(theta2)))
return solutions
# 사용 예시
l1, l2 = 1.0, 0.8 # 링크 길이
target_x, target_y = 1.2, 0.6 # 목표 좌표
solutions = inverse_kinematics_2link(target_x, target_y, l1, l2)
for i, (t1, t2) in enumerate(solutions):
label = "Elbow-Up" if i == 0 else "Elbow-Down"
print(f"{label}: θ₁ = {t1:.2f}°, θ₂ = {t2:.2f}°")출력 예시:
Elbow-Up: θ₁ = 5.65°, θ₂ = 52.41°
Elbow-Down: θ₁ = 47.06°, θ₂ = -52.41°
실전에서의 IK
ROS 2 환경에서는 MoveIt 2를 통해 IK를 사용합니다. MoveIt은 내부적으로 다양한 IK 솔버 플러그인을 지원합니다.
| IK 솔버 | 특징 |
|---|---|
| KDL | 기본 솔버, Jacobian 기반 수치 해법 |
| TRAC-IK | KDL 개선 버전, 더 높은 성공률 |
| IKFast | OpenRAVE 기반 해석적 솔버, 빠르지만 생성이 복잡 |
| BioIK | 진화 알고리즘 기반, 복잡한 제약 조건 처리 |
# MoveIt 2에서 IK를 사용하는 간단한 예시 (개념 코드)
from moveit.core.robot_state import RobotState
# 목표 위치/자세 설정
target_pose = Pose()
target_pose.position.x = 0.5
target_pose.position.y = 0.2
target_pose.position.z = 0.3
# IK 계산 — MoveIt이 내부적으로 설정된 IK 솔버를 호출
robot_state = RobotState(robot_model)
success = robot_state.set_from_ik(
joint_model_group, # 사용할 관절 그룹 (예: "arm")
target_pose, # 목표 위치/자세
timeout=0.1 # 타임아웃 (초)
)
if success:
joint_values = robot_state.get_joint_group_positions(joint_model_group)
print(f"IK 성공! 관절 각도: {joint_values}")
else:
print("IK 실패: 도달 불가능하거나 타임아웃")로봇뿐 아니라 게임 캐릭터의 발이 지형에 자연스럽게 닿게 하거나, 캐릭터가 물체를 집는 애니메이션에도 IK가 사용됩니다. Unity, Unreal Engine 등에서도 IK 시스템을 기본 제공합니다.
주의사항과 팁
- 특이점(Singularity): 로봇 팔이 완전히 펴지거나 접히면 Jacobian 행렬이 **특이(singular)**해져 IK 계산이 불안정해집니다. DLS(Damped Least Squares) 방법으로 완화할 수 있습니다.
- 작업 공간(Workspace): 목표 위치가 로봇의 도달 가능 영역 밖에 있으면 IK 해가 존재하지 않습니다. 사전에 도달 가능 여부를 확인하세요.
- 관절 제한(Joint Limits): 수학적으로 해가 존재하더라도, 실제 로봇의 관절 각도 제한을 넘으면 사용할 수 없습니다.
- 다중 해 선택: 여러 해 중 현재 자세에서 가장 가까운 해를 선택하면 부드러운 모션을 만들 수 있습니다.
- 실시간 제어: 수치적 방법을 사용할 때는 이전 해를 초기값으로 사용하면 수렴 속도가 크게 향상됩니다.
정리
| 항목 | 내용 |
|---|---|
| IK란? | 목표 위치/자세 → 관절 각도를 역으로 구하는 것 |
| FK와의 차이 | FK는 순방향(유일해), IK는 역방향(다중/무해 가능) |
| 풀이 방법 | 해석적(정확, 단순 구조) / 수치적(범용, 반복 계산) |
| ROS 2 | MoveIt 2 + IK 솔버 플러그인(KDL, TRAC-IK 등) |
| 핵심 주의점 | 특이점, 작업 공간, 관절 제한, 다중 해 선택 |
**IK는 "로봇이 원하는 곳에 손을 뻗게 만드는 수학"**입니다. FK가 "이렇게 움직이면 어디에 도달할까?"라는 질문이라면, IK는 "저기에 도달하려면 어떻게 움직여야 할까?"라는 질문에 답합니다.