# 從 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/)