承續上篇 Isaac Sim 的介紹 (文章鏈接), 讀者對於如何執行 Isaac Sim 以及它最基本的環境已經有了一些初步的瞭解了, 接下來我們就要來玩一下能不能在模擬環境上部署深度學習模型來讓 Jetbot 機器人 從無到有自己學會道路駕駛,例如下面的範例影片,透過模擬的 Jetbot 鏡頭看出去, 我們可以看到機器人確實有沿着道路在行走!
本篇文章是參考 Nvidia 官方的範例教學 (https://docs.omniverse.nvidia.com/app_isaacsim/app_isaacsim/sample_training_rl.html#jetbot-lane-following-sample) 做成的, 想要進一步瞭解的讀者可以去參考看看哦。
2. 準備道路模型
要讓機器人學會道路駕駛,最基本的就是要先有個道路可以讓機器人去跑, 我們在這邊使用樂高的道路平板來拼湊出基本的道路,好讓機器人可以學習如直走跟轉彎。
2.1. LeoCAD
- 首先,我們必須去下載LeoCAD, 一款專門用來畫樂高模型的繪圖軟體,請點選下方的鏈接來下載並安裝。
- 安裝完成後,啓動 LeoCAD,在右邊的零件表搜尋一下四種道路平板,
- 44336p01 Baseplate 32×32 Road 6-Stud Straight
- 44342p01 Baseplate 32×32 Road 6-Stud Curve
- 44341p01 Baseplate 32×32 Road 6-Stud T-Junction
- 44343p01 Baseplate 32×32 Road 6-Stud Crossroad
- 可以試着把四片平板組合起來,看看是不是可以拼成以下的道路圖。
- 那麼最後就是把這幾件平板輸出成 COLLADA 檔,準備做進一步的轉檔處理。
2.2. Blender
前面提過我們拿到了道路的 COLLADA 檔, 這是一種用來在多個3D軟體交換用的格式。 但是我們還得要用 Blender 再進行一次轉檔, 才能轉成可以在 Isaac Sim 渲染的圖檔。
- 下載並安裝 Blender
- 將剛剛輸出的 COLLADA 檔匯到 Blender 中
匯入後應該可以看到道路的圖檔顯示如下
- 接下來我們將每一塊零件的偏移量歸零,因爲等會要丟到 Isaac Sim 時,會用程式組裝出各種可能的道路, 所以我們必須確保零件的原點都是一致的。
- 從新命名每一個零件,方便我們待會匯入到 Isaac Sim 時比較好辨認。
- 最後輸出圖檔成 Isaac Sim 可以吃的 fbx 檔。
記得要在 Transform 那邊選擇 Z Up, X Forward。
輸出完成後,我們就會拿到下面四個圖檔。
- p44336p01.fbx
- p44342p01.fbx
- p44341p01.fbx
- p44343p01.fbx
2.3. 將圖檔匯入 Issac sim
接下來我們回到 Isaac Sim 中,我們要把前面的圖檔匯入到模擬環境中。 首先,開啓 Isaac Sim 並在左下角的 Content 中建立一個 Omniverse/localhost/Library/Props/Road_Tiles/Parts 的資料夾, 然後在右邊的空白欄位點右鍵,選擇 Import and Convert 來匯入 fbx 檔案。
假設我們前面的 fbx 檔案是存在 Download 這個資料夾, 我們就可以將他們全選並上傳到 Nucleus 伺服器, 記得在上傳的時候要勾選下面三個選項:
- Import Materials
- Import As Single USD
- Generate Smooth Normals
匯入後如下圖
最後檢查一下是否我們要的四塊道路圖檔都有被正確匯入了。
3. 開始訓練深度學習的模型
接下來的操作需要使用者有事先匯入 Isaac Sim 的 Asset 套件包, 裡面有機器學習的範例檔,如果不知道怎麼匯入的讀者可以去參考我們的 上一篇文章: Isaac Sim 的介紹 (文章鏈接)。
有別於之前的操作都是直接使用 Isaac Sim 的 圖形化界面, 這次我們啓動訓練模型的程式方法是必須從終端機開始。首先, 在電腦上打開一個終端機,並輸入下面的指令:
cd ~/.local/share/ov/pkg/isaac_sim-2021.1.1/
這個的意思是切換目錄到前面提到的 Isaac Sim 的 Asset 套件包的安裝位置。
然後修改 “python_samples/jetbot/road_environment.py” 這隻程式,將道路圖塊的路徑 改到我們剛剛放的地方,如下
# 1=I 2=L 3=T, 4=X
self.tile_usd = {
0: None,
1: {"asset": nucleus_server + "/Library/Props/Road_Tiles/Parts/p44336p01/p44336p01.usd", "offset": 180},
2: {"asset": nucleus_server + "/Library/Props/Road_Tiles/Parts/p44342p01/p44342p01.usd", "offset": 180},
3: {"asset": nucleus_server + "/Library/Props/Road_Tiles/Parts/p44341p01/p44341p01.usd", "offset": 180},
4: {"asset": nucleus_server + "/Library/Props/Road_Tiles/Parts/p44343p01/p44343p01.usd", "offset": 180},
} # list of tiles that can be spawned
3.1. 確保 GPU 的記憶題足夠訓練模型
筆者的開發環境所用的筆電有的顯卡是RTX 3070, 但即便是擁有8G的記憶體還是無法負荷預設的模型訓練參數, 所以我們會做以下的調整,縮小模型訓練時的吞吐量, 雖然會模型學習的會比較慢,但至少確保能夠正常運作。
我們修改 “python_samples/jetbot/jetbot_train.py” , 這隻程式是我們用來訓練的主程式。 裡面有一個地方是可以設定 batch size 的大小,這個會決定模型每次訓練的吞吐量, 以筆者的8G顯卡爲例,可以設定的最大 batch size 大概是1024。修改如下:
if args.loaded_checkpoint == "":
model = PPO(
"CnnPolicy",
env,
verbose=1,
tensorboard_log=args.tensorboard_dir,
policy_kwargs=policy_kwargs,
device="cuda",
n_steps=args.step_freq,
batch_size=1024,
n_epochs=50,
learning_rate=0.0001,
)
另外,在開始訓練前,建議關掉所有的 Isaac Sim 的軟體, 因爲那都會重複佔用到 GPU 的記憶體,我們只要保留由終端機執行 訓練程式所叫起的 Isaac Sim 就好。
一切準備就緒後我們就可以執行下面的指令來開始訓練了。
./python.sh python_samples/jetbot/jetbot_train.py
上面的指令會自動叫出模擬的圖形化界面,如果讀者覺得暫時不需要 花費算力去畫出模擬的3D圖,可以在後面加上 headless 來關閉圖形化界面, 等訓練完一段時間後,再開啓圖形化界面確認模型的訓練的效果也是可以的。
./python.sh python_samples/jetbot/jetbot_train.py --headless
4. 強化學習的訓練機制
熟悉深度學習的讀者一定知道在讓模型去做學習的時候,能否給模型一個好的回饋 是學習成敗的關鍵,例如以寵物分類問題來說,我們會給模型看到哪些圖片是貓,哪些圖片是狗, 藉此來讓模型去學習。但是對於學習自動駕駛來說,機器人可以做到決策其實複雜度更高, 比如說 Jetbot 可以隨著時間變化行走的方向跟速度,至於要怎麼判斷機器人走得好不好, 也許我們可以透過機器人的中心點到道路中間的距離來判斷,另外,機器人的行走速度可能也是 一個我們希望最佳化的量,好比說我們會希望機器人過彎的時候會懂得抄近路,而不是一味地死守道路中線。
當我們搞定好模型在學習這個問題的回饋之後,我們就可以來看一下具體模型的學習策略。 對於強化學習的問題而言,我們沒有辦法馬上知道模型此刻學的行爲好或不好,比如說 Jetbot 可能在直線上可以走得 很順,但是一直到轉彎處直接跑出界才發現其實它不會轉彎。在這個範例程式中,我們主要會用以下的技術來幫助模型的學習:
- 使用 Open AI 所提出的 Proximal Policy Optimization (PPO) 技術來做有效的強化學習, 簡單說就是在每一次的訓練回合中,都會先生成一個固定模型參數的代打,下去我們的模擬環境跑各種的測試, 然後我們再利用這些測試所蒐集的數據來生成一個資料集,回過頭更新我們之前的模型。其中的精妙之處 在於我們不會輕易的將我們正在學的模型一直丟到測試環境中去驗證,因爲這樣會導致模型在學習上很不穩定, 同時也沒有效率,變成說每次剛更新完的模型走一步測試後,這個資料就只用那麼一次而已。
- 使用 Issac Sim 的 Domain Randomization 機制來加強模型的韌性。如果讀者仔細觀察機器人在學習的過程中 其實場景是一直在變化的,我們的環境模擬程式不只會將我們前面的道路圖塊隨機拼湊成不同的環形道路外, 道路週遭的背景跟物品也都會隨機生成,爲的就是儘可能的讓機器人適應不同點情況,達到我們真正想要它學習的任務。
5. 檢視模型訓練的結果
以筆者的經驗,模型都需要經過兩萬多次以上的回合後,Jetbot 在道路上的行爲 才會收斂到我們所想像的自動駕駛,像是筆者的電腦(Intel i7 CPU + RTX 3070 GPU)大概會需要模型跑個一天的訓練才能達到 一個可以接受的表現。
那如果是想要看看我們模型的表現如何,可以先停掉訓練的程式, 釋放出可用的 GPU ,然後執行下面的程式
./python.sh python_samples/jetbot/jetbot_train.py --eval
程式會自動挑選目前爲止訓練最好的模型參數,然後套用在 Jetbot 跑道路模型的模擬上, 如下,讀者是否都能夠看到自己訓練的 Jetbot 都能夠沿着道路跑一遍自動駕駛呢?