LeRobot documentation

アクションの表現

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

アクションの表現

このガイドでは、LeRobotにおけるロボットアクションの異なる表現方法、それらの相互関係、および各表現の適用タイミングについて説明します。

ジョイント空間とエンドエフェクタ空間

アクションの表現について議論する前に、アクションが存在し得る2つの座標空間を理解しておくことが役立ちます。

ジョイントスペース

Joint-space actionsは各モーターの目標位置を直接指定します。6自由度のロボットアームとグripperを持つ場合、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のデフォルトです。シンプルで、運動学モデルを必要とせず、モーターコマンドに直接マッピングできます。初心者のセットアップ(SO-100、Koch)の多くは、joint-space actionsを使用しています。

エンドエフェクタ(EE)空間

エンドエフェクタ空間のアクションは、ロボットのツールチップ(グリップ)の所望の位置と姿勢をデカルト座標で指定します:

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

EE空間は、ピッキング&プレースングのようなタスクにおいて、グリップがどこに移動すべきかを直接記述するため、より直感的です。ただし、EEの姿勢と関節角度の間の変換には、運動学モデル(URDF)が必要です。

スペース間の変換

LeRobotは、RobotKinematicsを基盤として、ロボットのURDFモデルを読み込み、フォワードキネマティクスとインバースキネマティクスを用いて関節空間とEE空間の変換を行うプロセッサステップを提供します。

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空間のアクションを用いた記録、再生、評価の完全な動作例については、examples/so100_to_so100_EE/を参照してください。

絶対、相対、およびデルタアクション

ジョイント空間でもEE空間でも、アクション値は3つの異なる方法で表現できます。用語は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 = relative + current_state。

なぜ相対アクションを使用するのか? モデルはゼロを中心に予測するオフセットを学習します。これにより正規化が容易になり、より安定した学習につながります。また、すべてのチャンクが同じ現在の状態を参照するため、チャンク間の誤差蓄積が発生しません。

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 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は推論呼び出しごとに1回だけ状態をキャッシュし、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