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