---
# System prepended metadata

title: 從 Isaac Lab 的 MDP 架構理解 Managers 設定邏輯
tags: [Isaac-Lab, Isaac, MDP]

---

# 從 Isaac Lab 的 MDP 架構理解 Managers 設定邏輯


*以 Reach 任務為例的完整筆記*
> 以下內容來自 Nvidia 深度學習學院課程 -- 「Train Your Second Robot in Isaac Lab」
> 
## 1 前言：Managers 是什麼

在 Isaac Lab 中，**Managers** 是讓整個模擬世界能夠有「行為邏輯」的系統骨幹。
它們負責將強化學習的核心概念——**MDP（Markov Decision Process，馬可夫決策過程）**——具體化為模擬環境中的可執行邏輯。

MDP 的基本元素：

* **Action（行動）**：機器人能做什麼
* **Command（指令）**：任務要達成什麼
* **Observation（觀察）**：機器人能看到什麼
* **Termination（終止）**：任務何時結束
* **Event（事件）**：何時重置或切換狀態
* **Reward（獎勵）**：如何評價動作好壞
* **Curriculum（課程）**：如何逐步增加難度

而 Managers 架構，就是這些元素的「總指揮」。
每一個環節都以 `@configclass` 定義，並在 `reach_env_cfg.py` 這份設定檔中統一配置。

---

## 2 環境設定的起點

檔案位置：

```
/Reach/tasks/manager_based/reach/reach_env_cfg.py
```

這份設定檔將所有 Managers 統一放在一起。
你可以把它想成是「Reach 任務的總設計藍圖」。

這些設定依序被 Isaac Lab 的 `SceneManager`、`TaskManager`、`PhysicsManager` 等模組讀取，
用來生成整個訓練環境。

---

## 3 MDP 函式的來源

Isaac Lab 的管理系統主要透過 `mdp` 模組運作。
它提供兩種函式來源：

### 3.1 內建 MDP 函式（Built-in）

這些是 Isaac Lab 已經定義好的常見功能，例如：

* `mdp.joint_pos_rel`：取得關節位置
* `mdp.time_out`：控制訓練時間終止
* `mdp.position_command_error`：計算末端執行器與目標之間的距離

這些函式可直接作為配置的 `func` 參數被呼叫。

### 3.2 自訂 MDP 函式（Custom）

若內建函式無法滿足需求，就在專案目錄中建立一個 `mdp/` 資料夾，
撰寫自訂函式以擴充行為，例如：

* 特殊的距離誤差評估
* 特定任務條件下的自訂獎勵

---

## 4 Actions：定義機器人能做什麼

「Action」是代理人能夠採取的動作。
在 Reach 任務中，機械手臂有六個旋轉關節（Revolute Joints），
因此使用 `JointPositionActionCfg` 來描述行動空間。

```python
@configclass
class ActionsCfg:
    """Action specifications for the MDP."""

    arm_action: ActionTerm = mdp.JointPositionActionCfg(
        asset_name="robot",
        joint_names=[
            "shoulder_pan_joint", "shoulder_lift_joint", "elbow_joint",
            "wrist_1_joint", "wrist_2_joint", "wrist_3_joint"
        ],
        scale=1,
        use_default_offset=True,
        debug_vis=True
    )
```

說明：

* `asset_name`：要控制的物件名稱
* `joint_names`：要控制的關節（可用正規表達式如 `joint_.*`）
* `scale`：行動輸入的比例
* `use_default_offset`：是否使用關節預設偏移量
* `debug_vis`：是否顯示除錯視覺化

---

## 5 Commands：定義要達成的目標

「Command」是任務層級的指令，
與「Action」不同的是，它描述「想達到什麼」而非「怎麼做」。

以下的範例指定了機械手臂末端執行器（end-effector）在空間中的隨機目標範圍。

```python
@configclass
class CommandsCfg:
    """Command terms for the MDP."""

    ee_pose = mdp.UniformPoseCommandCfg(
        asset_name="robot",
        body_name="ee_link",
        resampling_time_range=(4.0, 4.0),
        debug_vis=True,
        ranges=mdp.UniformPoseCommandCfg.Ranges(
            pos_x=(0.35, 0.65),
            pos_y=(-0.2, 0.2),
            pos_z=(0.15, 0.5),
            roll=(0.0, 0.0),
            pitch=(math.pi / 2, math.pi / 2),
            yaw=(-3.14, 3.14),
        ),
    )
```

說明：

* 目標位置每 4 秒重新生成一次
* 指定末端執行器 `ee_link` 的活動範圍
* `ranges` 定義了空間與姿態（位姿 pose）的隨機取樣範圍

---

## 6 Observations：觀察環境狀態

觀察（Observation）定義代理人從環境中能夠「看到」哪些資訊。

在 Reach 任務中，我們需要知道：

* 關節的位置與速度
* 末端執行器的目標位置
* 上一步行動的輸入

```python
@configclass
class ObservationsCfg:
    """Observation specifications for the MDP."""

    @configclass
    class PolicyCfg(ObsGroup):
        """Observations for policy group."""

        joint_pos = ObsTerm(func=mdp.joint_pos_rel, noise=Unoise(n_min=-0.01, n_max=0.01))
        joint_vel = ObsTerm(func=mdp.joint_vel_rel, noise=Unoise(n_min=-0.01, n_max=0.01))
        pose_command = ObsTerm(func=mdp.generated_commands, params={"command_name": "ee_pose"})
        actions = ObsTerm(func=mdp.last_action)

        def __post_init__(self):
            self.enable_corruption = True
            self.concatenate_terms = True

    policy: PolicyCfg = PolicyCfg()
```

說明：

* 每個 `ObsTerm` 代表一種觀察來源
* `noise=Unoise(...)` 模擬感測器雜訊，提升模型穩健性
* `enable_corruption=True` 允許資料被隨機擾動（訓練時常用技巧）
* `concatenate_terms=True` 將多個觀察項目組合為一個長向量

---

## 7 Terminations：何時結束任務

Termination 決定「任務何時結束」。
最簡單的條件是超時（timeout）。

```python
@configclass
class TerminationsCfg:
    """Termination terms for the MDP."""

    time_out = DoneTerm(func=mdp.time_out, time_out=True)
```

這行代表：
每一個訓練 episode 到達時間上限時，自動結束。

在更複雜的任務中，還可以加入：

* 碰撞條件（例如與牆壁接觸即結束）
* 關節角度超出安全範圍
* 成功達到目標位置

---

## 8 Events：任務過程中的事件

Event 負責定義「任務內部狀態變化」或「重置條件」。

Reach 任務中的常見事件是「重置機械手臂姿勢」。

```python
@configclass
class EventCfg:
    """Configuration for events."""

    reset_robot_joints = EventTerm(
        func=mdp.reset_joints_by_scale,
        mode="reset",
        params={
            "position_range": (0.75, 1.25),
            "velocity_range": (0.0, 0.0),
        },
    )
```

說明：

* 使用內建函式 `mdp.reset_joints_by_scale`
* 每次重置時，關節位置在 ±25% 的隨機範圍內
* 速度初始為 0

這幾行程式就能完成「一鍵重置世界」的功能，
而在實體機器人上，要達成同樣的動作往往需數百行程式與安全檢查。

---

## 9 Rewards：任務的學習信號

Reward 是強化學習的核心，
它告訴代理人「做得好或不好」。

在 Reach 任務中，獎勵由多項項目組成：

```python
@configclass
class RewardsCfg:
    """Reward terms for the MDP."""

    end_effector_position_tracking = RewTerm(
        func=mdp.position_command_error,
        weight=-0.2,
        params={"asset_cfg": SceneEntityCfg("robot", body_names=["ee_link"]), "command_name": "ee_pose"},
    )

    end_effector_position_tracking_fine_grained = RewTerm(
        func=mdp.position_command_error_tanh,
        weight=0.1,
        params={"asset_cfg": SceneEntityCfg("robot", body_names=["ee_link"]), "std": 0.1, "command_name": "ee_pose"},
    )

    action_rate = RewTerm(func=mdp.action_rate_l2, weight=-0.0001)

    joint_vel = RewTerm(
        func=mdp.joint_vel_l2,
        weight=-0.0001,
        params={"asset_cfg": SceneEntityCfg("robot")},
    )
```

獎勵結構：

1. **位置追蹤誤差**：鼓勵末端執行器接近目標
2. **細粒度誤差**：使用雙曲正切函數平滑化誤差
3. **行動變化率懲罰**：鼓勵穩定動作
4. **關節速度懲罰**：避免劇烈晃動

Isaac Lab 的核心演算法會自動計算這些項目的值，
代理人藉此學會平衡速度、穩定性與精準度。

---

## 10 Curriculum：逐步增加任務難度

Curriculum（課程學習）讓任務的訓練能循序漸進。
我們可以在特定訓練步數後，修改獎勵權重以引導學習方向。

```python
@configclass
class CurriculumCfg:
    """Curriculum terms for the MDP."""

    action_rate = CurrTerm(
        func=mdp.modify_reward_weight, 
        params={"term_name": "action_rate", "weight": -0.005, "num_steps": 4500}
    )

    joint_vel = CurrTerm(
        func=mdp.modify_reward_weight, 
        params={"term_name": "joint_vel", "weight": -0.001, "num_steps": 4500}
    )
```

這裡設定在 4500 步後，增加懲罰權重，
迫使 agent 產生更平滑、更穩定的運動。

---

## 11 總結：Managers 架構的整體邏輯

| 模組名稱            | 功能說明      | 對應設定類別            |
| --------------- | --------- | ----------------- |
| **Action**      | 定義可執行的動作  | `ActionsCfg`      |
| **Command**     | 設定任務目標    | `CommandsCfg`     |
| **Observation** | 收集環境資訊    | `ObservationsCfg` |
| **Termination** | 決定任務結束條件  | `TerminationsCfg` |
| **Event**       | 控制重置與特殊事件 | `EventCfg`        |
| **Reward**      | 提供學習信號    | `RewardsCfg`      |
| **Curriculum**  | 動態調整任務難度  | `CurriculumCfg`   |

整體流程：

```
Actions → 改變環境
↓
Observations → 回饋狀態
↓
Rewards → 評估表現
↓
Terminations / Events → 控制任務迴圈
↓
Curriculum → 持續優化難度
```

Managers 架構的精髓在於：

> **一切都以設定（Configuration）為核心，
> 而非硬寫程式碼。**

---

## 12 結語

這套設計讓 Isaac Lab 能在不改主程式邏輯的情況下：

* 快速重構任務
* 擴展至多機器人、多環境
* 保持代碼模組化與資料驅動化

換言之，Managers 架構是「Isaac Lab 能大規模產生智能體的關鍵基礎」。
每一個設定類別都是一個可插拔的模組，
共同組成了強化學習的完整循環世界。

### Next → 123

---
希望我的內容對你有所幫助，想看到更多內容歡迎追蹤我的 IG、Threads 等平台。
Threads：[@minimalist_shine](https://www.threads.com/@minimalist_shine)
IG：[@minimalist_shine](https://www.instagram.com/minimalist_shine/)