LeRobot documentation

액션 표현

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

액션 표현

이 가이드에서는 LeRobot에서 로봇 액션을 표현하는 다양한 방법, 각 방법 간의 관계, 그리고 각각을 언제 사용해야 하는지를 설명합니다.

Joint Space vs End-Effector Space

액션 표현에 대해 논의하기 전에, 액션이 존재할 수 있는 두 가지 좌표 공간을 이해하는 것이 도움이 됩니다.

Joint Space

Joint-space actions은 각 모터의 목표 위치를 직접 지정합니다. 6-DOF 암과 그립퍼가 있는 경우, joint-space action은 다음과 같은 형태일 수 있습니다:

action = [shoulder_pan: 45.0, shoulder_lift: -20.0, elbow: -30.0, wrist_pitch: 10.0, wrist_roll: 0.0, wrist_yaw: 5.0, gripper: 0.8]

Joint space는 LeRobot의 기본 설정입니다. 간단하며, kinematics 모델이 필요하지 않고, 모터 명령으로 직접 매핑됩니다. 대부분의 입문용 설정(SO-100, Koch)은 joint-space actions를 사용합니다.

엔드 이펙터(EE) 공간

End-effector-space actions는 로봇의 도구 팁(그리퍼)의 Cartesian 좌표계에서의 원하는 위치와 방향을 지정합니다:

action = [x: 0.25, y: -0.10, z: 0.15, wx: 0.0, wy: 0.0, wz: 0.1, gripper: 0.8]

EE space is more intuitive for tasks like pick-and-place because it directly describes where the gripper should go, but it requires a kinematics model (URDF) to convert between EE poses and joint angles.

공간 간 변환

LeRobot는 전방 및 역학술을 사용하여 관절 공간과 EE 공간 간의 변환을 위한 프로세서 단계를 제공합니다. 이 단계들은 로봇의 URDF 모델을 로드하는 RobotKinematics를 기반으로 구축되었습니다.

from lerobot.model.kinematics import RobotKinematics
from lerobot.robots.so_follower.robot_kinematic_processor import (
    ForwardKinematicsJointsToEE,
    InverseKinematicsEEToJoints,
)

kinematics = RobotKinematics(
    urdf_path="./SO101/so101_new_calib.urdf",
    target_frame_name="gripper_frame_link",
    joint_names=["shoulder", "elbow", "wrist_pitch", "wrist_roll", "wrist_yaw"],
)

# Joints → EE (for observations: "where is my gripper?")
fk_step = ForwardKinematicsJointsToEE(kinematics=kinematics, motor_names=[...])

# EE → Joints (for actions: "move my gripper here")
ik_step = InverseKinematicsEEToJoints(kinematics=kinematics, motor_names=[...])

SO-100 암에서 EE-space 동작으로 녹화, 재생 및 평가하는 완전한 작동 예제는 examples/so100_to_so100_EE/를 참조하세요.

절대, 상대 및 델타 액션

관절 공간이나 EE 공간에서 작업하든 상관없이, 동작 값은 세 가지 방식으로 표현할 수 있습니다. 용어는 UMI (Chi et al., 2024)를 따릅니다.

절대 액션(LeRobot 기본값)

각 액션은 대상 위치를 직접 지정합니다.

예시 (공통 공간, 청크 4):

current_state = [45.0, -30.0, 10.0]

action_chunk = [
    [46.0, -29.0, 11.0],   # go to 46, -29, 11
    [47.5, -27.0, 12.0],   # go to 47.5, -27, 12
    [49.0, -25.0, 13.5],   # go to 49, -25, 13.5
    [50.0, -24.0, 15.0],   # go to 50, -24, 15
]

각 값은 로봇의 좌표계 내의 목표 위치입니다. 단순하고 직관적이지만 일관된 전역 좌표계를 요구합니다. 이는 LeRobot의 기본 설정입니다.

상대적 액션(OpenPI / pi0에서 사용)

예측 시점의 현재 상태를 기준으로, 청크의 각 동작은 해당 상태에서의 오프셋입니다. 청크 내 모든 동작은 동일한 기준점을 공유합니다:

current_state = [45.0, -30.0, 10.0]

relative_chunk = [
    [1.0,  1.0, 1.0],   # +1 from current → target 46, -29, 11
    [2.5,  3.0, 2.0],   # +2.5 from current → target 47.5, -27, 12
    [4.0,  5.0, 3.5],   # +4 from current → target 49, -25, 13.5
    [5.0,  6.0, 5.0],   # +5 from current → target 50, -24, 15
]

변환은 간단합니다: relative = absolute - current_state. absolute를 복원하려면: absolute = relative + current_state.

왜 상대 동작을 사용합니까? 모델은 0을 중심으로 한 오프셋을 예측하도록 학습되며, 이는 정규화가 더 쉽고 더 안정적인 학습으로 이어집니다. 모든 청크가 동일한 현재 상태를 참조하므로 청크 간에 오류가 누적되지 않습니다.

Delta Actions(순차적 차이)

각 동작은 이전 동작에서 벗어난 값(첫 단계의 경우 현재 상태 기준)입니다:

current_state = [45.0, -30.0, 10.0]

delta_chunk = [
    [1.0,  1.0, 1.0],   # current → 46, -29, 11
    [1.5,  2.0, 1.0],   # previous action → 47.5, -27, 12
    [1.5,  2.0, 1.5],   # previous action → 49, -25, 13.5
    [1.0,  1.0, 1.5],   # previous action → 50, -24, 15
]

여기서 각 단계는 이전 단계에 상대적입니다. 절대 위치를 복원하려면 모든 이전 델타를 합산해야 하며, 이는 시간이 지남에 따라 오류가 누적됨을 의미합니다. UMI는 이 이유로 인해 이러한 표현 방식에 대해 명시적으로 반대합니다.

시각적 비교

아래 그림(UMI, Chi et al., 2024의 그림을 기반으로 함)은 핵심적인 차이를 보여줍니다. 상대 궤적(relative trajectory)을 사용하면 청크 내 모든 동작이 동일한 기점(현재 상태)을 기준으로 하므로, 새로운 추론 단계에서 기준점을 깔끔하게 초기화할 수 있습니다. 델타(delta)를 사용하면 각 동작이 이전 동작에 의존하므로 오류가 누적됩니다. 절대(Absolute) 동작은 일관된 전역 좌표계를 요구합니다.

Relative Trajectory as Action Representation (UMI, Chi et al., 2024)

LeRobot에서 상대 동작 사용

LeRobot는 프로세서 파이프라인 내에서 절대 동작과 상대 동작을 상호 변환하기 위해 RelativeActionsProcessorStep을 제공합니다. pi0, pi0.5, pi0_fast가 상대 동작을 지원하는 방식이 바로 이 메커니즘입니다.

Note: All pi models (pi0, pi0.5, pi0fast) apply relative conversion _before normalization (relative → normalize), so the normalizer always sees delta (relative) values. This means relative action stats are required for all of them when training with use_relative_actions=true. In pi0_fast the RelativeActionsProcessorStep only modifies the action — the state observation is unchanged — so NormalizerProcessorStep still runs before the state tokenizer and the tokenizer continues to receive normalized state as expected.

작동 방식

학습(전처리) 중에 모델이 액션을 확인하기 전에 절대 좌표에서 상대 좌표로 변환됩니다:

raw absolute action → RelativeActionsProcessorStep → normalize → model

추론(후처리) 단계에서 모델 예측값은 로봇으로 전송되기 전에 절대값으로 변환됩니다:

model output → unnormalize → AbsoluteActionsProcessorStep → robot

AbsoluteActionsProcessorStep는 페어링된 RelativeActionsProcessorStep에서 캐시된 현재 상태를 읽으므로, 두 단계는 함께 연결되어야 합니다(정책 팩토리가 자동으로 처리합니다).

pi 계열(pi0, pi0.5, pi0_fast)에 대한 상대 동작 활성화

1단계: 데이터셋에 대한 상대적 동작 통계를 사전 계산합니다:

lerobot-edit-dataset \
    --repo_id your_dataset \
    --new_repo_id your_dataset \
    --operation.type recompute_stats \
    --operation.overwrite true \
    --operation.relative_action true \
    --operation.chunk_size 50 \
    --operation.relative_exclude_joints "['gripper']"

2단계: 상대 동작을 활성화하여 학습합니다:

lerobot-train \
    --dataset.repo_id=your_dataset \
    --policy.type=pi0 \
    --policy.use_relative_actions=true \
    --policy.relative_exclude_joints='["gripper"]'

relative_exclude_joints 매개변수는 절대 공간에 유지되어야 하는 조인트를 지정합니다. 예를 들어, 그리퍼 명령은 일반적으로 이진(열기/닫기)이며 상대 인코딩의 이점을 받지 못합니다.

action_feature_names를 정의하는 정책 구성의 경우, make_policy는 데이터셋 액션 피처의 names 메타데이터에서 이 목록을 채웁니다. Names는 평탄한 시퀀스이거나, 값이 모두 리스트 또는 튜플인 사전일 수 있습니다. 예를 들어, {"arm": ["shoulder", "elbow"], "hand": ["gripper"]}은 그룹 키가 아닌 ["shoulder", "elbow", "gripper"]가 됩니다. 그룹 삽입 순서와 그룹 내 순서가 보존되므로, 액션 벡터와 동일한 순서로 이름을 선언해야 합니다. 레거시 이름-인덱스 매핑은 키 순서 동작을 유지합니다.

상대적 동작과 RTC의 결합

RTC는 높은 주기로 정책 추론을 실행하며, 전체 청크를 기다리지 않고 예측되는 대로 로봇에 액션을 전송합니다. 상대 액션과 RTC는 완전히 호환됩니다. 상대 모드에서 모든 청크는 동일한 현재 상태(추론 시작 시점에 캡처됨)를 참조하므로, 로봇이 이미 이동했더라도 청크 내 각 예측 액션은 여전히 유효한 오프셋으로 유지됩니다. 특별한 처리는 필요하지 않으며, RelativeActionsProcessorStep은 추론 호출당 상태를 한 번만 캐시하고 AbsoluteActionsProcessorStep은 스트리밍 출력의 모든 액션에 해당 상태를 적용합니다.

상대 동작과 EE 공간 결합

상대 동작은 조인트 공간과 EE 공간 모두에서 작동합니다. 예를 들어, 데이터셋에 EE 동작이 저장되어 있는 경우, 상대 인코딩은 이를 현재 EE 자세로부터의 오프셋으로 변환합니다:

current_ee_state = [x: 0.25, y: -0.10, z: 0.15, gripper: 0.8]

absolute_ee_chunk = [
    [0.26, -0.09, 0.16, 0.8],
    [0.28, -0.07, 0.18, 0.8],
]

relative_ee_chunk = [
    [0.01,  0.01, 0.01, 0.0],   # offset from current EE pose
    [0.03,  0.03, 0.03, 0.0],   # offset from current EE pose
]

처리 파이프라인 요약

여기서 다양한 프로세서가 어떻게 조합되는지 보여줍니다. 각 화살표는 프로세서 단계를 나타내며, RobotProcessorPipeline 또는 PolicyProcessorPipeline에서 체인 형태로 연결할 수 있습니다:

                    ┌─────────────────────────────────────────┐
   Action Space     │   Joint Space  ←──IK──→  EE Space      │
                    │   ForwardKinematicsJointsToEE           │
                    │   InverseKinematicsEEToJoints           │
                    └─────────────────────────────────────────┘

                    ┌─────────────────────────────────────────┐
   Representation   │   Absolute  ←────→  Relative            │
                    │   RelativeActionsProcessorStep (pre)    │
                    │   AbsoluteActionsProcessorStep (post)   │
                    └─────────────────────────────────────────┘

                    ┌─────────────────────────────────────────┐
   Normalization    │   Raw  ←────→  Normalized               │
                    │   NormalizerProcessorStep (pre)         │
                    │   UnnormalizerProcessorStep (post)      │
                    └─────────────────────────────────────────┘

일반적인 학습 전처리기는 raw absolute joint actions → relative → normalize를 연쇄적으로 적용할 수 있습니다. 일반적인 추론 후처리기는 unnormalize → absolute → (optionally IK to joints)입니다.

참고

Update on GitHub