IK(역기구학)란 무엇인가

개요

**IK (Inverse Kinematics, 역기구학)**는 로봇 공학에서 가장 핵심적인 개념 중 하나입니다. 로봇 팔이 특정 위치의 물체를 잡으려면, 각 관절을 몇 도씩 회전해야 하는지 계산해야 합니다. 이 "목표 위치 → 관절 각도" 역방향 계산이 바로 역기구학입니다.

핵심 요약: FK는 "관절 각도 → 끝점 위치"를 구하고, IK는 "끝점 위치 → 관절 각도"를 구한다.

IK 다중 해 예시 (Wikimedia Commons)


FK vs IK 비교

**정기구학(FK, Forward Kinematics)**과 **역기구학(IK, Inverse Kinematics)**은 서로 반대 방향의 문제를 풀고 있습니다.

구분FK (정기구학)IK (역기구학)
입력각 관절 각도 (θ1,θ2,,θn)(\theta_1, \theta_2, \dots, \theta_n)엔드 이펙터 목표 위치/자세 (x,y,z,R)(x, y, z, R)
출력엔드 이펙터 위치/자세각 관절 각도
해의 개수항상 유일한 해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)**을 순서대로 곱하여 엔드 이펙터의 위치를 구합니다.

Tn0=T10T21T32Tnn1T_n^0 = T_1^0 \cdot T_2^1 \cdot T_3^2 \cdots T_n^{n-1}

여기서 Tii1T_i^{i-1}은 관절 i1i-1에서 관절 ii로의 **동차 변환 행렬(Homogeneous Transformation Matrix)**입니다.

2개의 링크를 가진 평면 로봇 팔의 경우, FK로 엔드 이펙터 위치를 구하면:

x=l1cosθ1+l2cos(θ1+θ2)x = l_1 \cos\theta_1 + l_2 \cos(\theta_1 + \theta_2)

y=l1sinθ1+l2sin(θ1+θ2)y = l_1 \sin\theta_1 + l_2 \sin(\theta_1 + \theta_2)

반대로 IK는 목표 좌표 (x,y)(x, y)로부터 θ1\theta_1, θ2\theta_2를 구합니다:

cosθ2=x2+y2l12l222l1l2\cos\theta_2 = \frac{x^2 + y^2 - l_1^2 - l_2^2}{2 l_1 l_2}

θ2=atan2(±1cos2θ2,  cosθ2)\theta_2 = \text{atan2}\left(\pm\sqrt{1 - \cos^2\theta_2},\; \cos\theta_2\right)

θ1=atan2(y,x)atan2(l2sinθ2,  l1+l2cosθ2)\theta_1 = \text{atan2}(y, x) - \text{atan2}\left(l_2 \sin\theta_2,\; l_1 + l_2 \cos\theta_2\right)

포인트: θ2\theta_2±\pm 부호에서 알 수 있듯이, 같은 목표 위치에 대해 **"팔꿈치 위(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으로 구현한 예시입니다.

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-IKKDL 개선 버전, 더 높은 성공률
IKFastOpenRAVE 기반 해석적 솔버, 빠르지만 생성이 복잡
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 2MoveIt 2 + IK 솔버 플러그인(KDL, TRAC-IK 등)
핵심 주의점특이점, 작업 공간, 관절 제한, 다중 해 선택

**IK는 "로봇이 원하는 곳에 손을 뻗게 만드는 수학"**입니다. FK가 "이렇게 움직이면 어디에 도달할까?"라는 질문이라면, IK는 "저기에 도달하려면 어떻게 움직여야 할까?"라는 질문에 답합니다.