[AI] OpenPilot C3X/C4 UI 模擬器操作教學:Windows 11+WSL2 桌面預覽
openpilot C3X/C4 UI 模擬器操作教學:Windows 11+WSL2 桌面預覽
本文介紹如何在 Windows 11 的 WSL2 環境中執行 openpilot 原生 UI, 並分別模擬 C3X/tizi 與 C4 的畫面配置。
這套方法不需要連接 comma 裝置、Panda 或車輛 CAN, 而是利用獨立的 Params 與 Cereal Fake Message Publisher, 提供 UI 所需的空白訊息,讓 openpilot UI 可以在 WSLg 視窗中啟動。
這不是完整的車輛模擬器,也不會輸出 CAN 訊號。它只能用來檢查 UI、字型、翻譯、按鈕、設定頁面、警示文字及基本排版,不能取代 C3X/C4 實機與實車驗證。
一、模擬器能測什麼?
可以先在電腦上檢查
- openpilot UI 是否能正常啟動。
- 中文字型是否正確顯示。
- Git LFS 圖片與字型資源是否完整。
- 設定頁面與初始設定頁面。
- 警示文字、按鈕及 HUD 排版。
- C3X/tizi 大畫面配置。
- C4 預設固定畫布的桌面呈現。
- 不同 Git branch 或 commit 之間的 UI 差異。
- 同時開啟兩個版本進行畫面比對。
不能取代的測試
- Camera、modeld 與影像辨識。
- Panda、CAN 與車型辨識。
- 方向盤、ACC、煞車及 safety 驗證。
- C3X/C4 GPU 實際效能。
- 觸控、亮度、自動調光及溫度表現。
- 實際安裝於車內時的可讀性。
二、C3X 與 C4 模式差異
| 模擬目標 | UI 類型 | 必要環境變數 | 注意事項 |
|---|---|---|---|
| C3X | tizi/tici 大畫面 | BIG=1 |
不要使用 BIG_UI=1 |
| C4 | 預設 UI | 不設定 BIG |
維持 UI 預設畫布,不設定 SCALE |
BIG=1
不是:
BIG_UI=1
此 Fork 的 C3X 對應 UI 類型為 tizi。
啟用 BIG=1 後,會使用較大的 tizi/tici 畫面配置,
原生畫布通常為 2160 × 1080。
C4 模擬則沿用 UI 預設尺寸。為了讓桌面畫面盡可能接近實機排版,
不要額外設定 SCALE=0.75、SCALE=1.5 或其他縮放值。
三、模擬器架構
openpilot UI
│
├── Raylib/WSLg 視窗
├── 獨立 Params 資料夾
└── Cereal Fake msgq 假資料源
每一個模擬器視窗都必須有自己的:
- Repository 或 worktree。
PARAMS_ROOT。CEREAL_FAKE_PREFIX。OPENPILOT_PREFIX。/dev/shm/msgq_<prefix>。- Fake Message Publisher。
如果兩個 UI 共用 Params 或 Fake msgq 前綴,可能會出現資料互相污染、
卡在教學頁面或 MultiplePublishersError。
四、Windows 與 WSL2 前置環境
建議環境:
- Windows 11。
- WSL2。
- Ubuntu 22.04。
- WSLg。
- 可正常啟動的 openpilot Python virtual environment。
- 已準備好的
opendbc_repo與msgq_repo。
1. 安裝 Ubuntu 22.04
以系統管理員身分開啟 PowerShell:
wsl --install -d Ubuntu-22.04
完成 Ubuntu 使用者建立後,確認 WSL 狀態:
wsl --list --verbose
wsl --status
wsl --version
wsl --update
Ubuntu 應顯示為 WSL 2。Windows 11 的 WSLg 可以直接顯示 Linux GUI, 一般不需要另外安裝 X Server。
2. 確認 WSLg
wsl -d Ubuntu-22.04 -- bash -lc 'echo $WAYLAND_DISPLAY; echo $DISPLAY'
也可以檢查 OpenGL:
wsl.exe -d Ubuntu-22.04 -- glxinfo -B
3. 安裝基本套件
進入 Ubuntu 後執行:
sudo apt update
sudo apt install -y \
build-essential \
git \
git-lfs \
libgl1-mesa-dev \
libegl1-mesa-dev \
libglfw3 \
libglfw3-dev \
libzmq3-dev \
fonts-noto-cjk
初始化 Git LFS:
git lfs install
若該 branch 的建置工具明確顯示缺少 imgui,再針對 openpilot 的 virtual environment 安裝:
~/.local/bin/uv pip install \
--python ~/openpilot/.venv/bin/python \
imgui
不建議尚未看到錯誤就預先安裝大量 Python 套件。 不同 Fork 與 commit 的相依套件可能不同,應優先依照該 Repository 的 README 或 setup script 建立環境。
五、準備 openpilot Repository
建議不同版本使用獨立 Repository 或 Git worktree, 不要在同一個 working tree 中反覆切換正在開發的 branch。
範例:Clone 模擬器專用 Repository
Windows PowerShell:
cd C:\Users\<USER>\Documents\Codex
git clone https://github.com/KingChang168/openpilot.git openpilot-ui-sim
cd openpilot-ui-sim
git fetch origin --tags --prune
git switch --detach origin/main
$env:GIT_LFS_SKIP_SMUDGE='1'
git submodule update --init --recursive opendbc_repo msgq_repo
git lfs pull --include="openpilot/selfdrive/assets/**,openpilot/sunnypilot/selfdrive/assets/**"
切換其他 branch
git status --short --branch
git fetch origin <branch>:refs/remotes/origin/<branch>
git switch --detach origin/<branch>
git submodule update --init --recursive opendbc_repo msgq_repo
git lfs pull --include="openpilot/selfdrive/assets/**,openpilot/sunnypilot/selfdrive/assets/**"
若主 Repository 已更新,但
opendbc_repo 或 msgq_repo
仍停留在舊 SHA,可能造成 import、Cereal schema 或原生模組不相容。
模擬工作目錄不建議直接修改正式 branch,也不要 force push。 測試產生的 Params、log、route、build output 與 screenshot 也不要提交進 Repository。
六、設定模擬器環境變數
以下假設:
- Repository:
/home/kingchang/openpilot-main - Python:
/home/kingchang/openpilot/.venv/bin/python - 模擬器名稱:
main
先設定環境變數:
export REPO=/home/kingchang/openpilot-main
export PYTHON_BIN=/home/kingchang/openpilot/.venv/bin/python
export SIM_PREFIX=main
export PARAMS_ROOT=/tmp/openpilot-ui-main-params
export PYTHONPATH="$REPO:$REPO/opendbc_repo:$REPO/msgq_repo"
mkdir -p "$PARAMS_ROOT"
mkdir -p "/dev/shm/msgq_${SIM_PREFIX}"
若 Repository 位於 Windows 磁碟,例如:
/mnt/c/Users/kingchang.ECS/Documents/Codex/openpilot
一樣可以使用,但 SCons 掃描 Windows 檔案系統時通常比較慢。 若需要頻繁建置,建議將 checkout 放在 WSL ext4,例如:
~/src/openpilot-ui-sim
七、建立獨立 Params
不要使用真實 C3X/C4 裝置上的 Params, 也不要讓兩個模擬器共用同一個 Params 目錄。
執行以下指令寫入模擬器 Params:
env \
OPENPILOT_PREFIX="$SIM_PREFIX" \
PARAMS_ROOT="$PARAMS_ROOT" \
PYTHONPATH="$PYTHONPATH" \
"$PYTHON_BIN" - <<'PY'
from openpilot.common.params import Params
p = Params()
values = {
"HasAcceptedTerms": "2",
"HasAcceptedTermsSP": "1.0",
"CompletedTrainingVersion": "0.2.0",
"CompletedSunnylinkConsentVersion": "-1",
}
for key, value in values.items():
try:
p.put(key, value)
except Exception as e:
print(f"skip {key}: {e}")
try:
p.put_bool("IsDriverViewEnabled", False)
except Exception as e:
print(f"skip IsDriverViewEnabled: {e}")
PY
這些 Params 主要用來略過:
- Terms 頁面。
- SunnyLink consent。
- Training 教學。
- Driver Monitoring 教學或 Driver View。
不同 Fork 或 commit 的 Param key 可能不同。
如果出現 UnknownKeyName,應檢查該版本的:
openpilot/common/params_keys.h
不要因為某個 key 寫入失敗,就直接假設它已經生效。
重新測試 Onboarding
只刪除該模擬器自己的 Params:
rm -rf "$PARAMS_ROOT"
刪除後若要再次略過教學頁面,必須重新建立 Params 並重新執行前面的寫入指令。
八、建立 Fake Message Publisher
openpilot UI 會訂閱許多 Cereal services。 在沒有實機 daemon 的情況下,需要建立一個 Fake Publisher, 週期性送出空白 message。
建立檔案:
nano ~/start_ui_publisher.py
貼入以下內容:
from openpilot.cereal import messaging, services
import time
publishers = []
for name in services.SERVICE_LIST:
if name == "uiDebug":
continue
try:
publishers.append((name, messaging.PubMaster([name])))
except Exception:
pass
while True:
for name, publisher in publishers:
try:
publisher.send(name, messaging.new_message(name))
except Exception:
pass
time.sleep(0.1)
uiDebug 由 UI 本身擁有。如果 Fake Publisher 同時發布,
可能造成 multiple publishers 衝突。
啟動 Publisher
nohup env \
CEREAL_FAKE=1 \
CEREAL_FAKE_PREFIX="$SIM_PREFIX" \
OPENPILOT_PREFIX="$SIM_PREFIX" \
PARAMS_ROOT="$PARAMS_ROOT" \
PYTHONPATH="$PYTHONPATH" \
"$PYTHON_BIN" ~/start_ui_publisher.py \
>"/tmp/openpilot-ui-${SIM_PREFIX}-publisher.log" \
2>&1 \
</dev/null &
確認 Message Socket
test -e "/dev/shm/msgq_${SIM_PREFIX}/deviceState" && echo READY
也可以直接查看:
ls -l "/dev/shm/msgq_${SIM_PREFIX}/deviceState"
看到 deviceState 後,才代表 Fake Publisher 已經建立訊息通道。
九、啟動 C4 UI 模擬器
C4 模式沿用 UI 預設畫面,不設定 BIG,
也不要額外設定 SCALE。
cd "$REPO"
env \
CEREAL_FAKE=1 \
CEREAL_FAKE_PREFIX="$SIM_PREFIX" \
OPENPILOT_PREFIX="$SIM_PREFIX" \
PARAMS_ROOT="$PARAMS_ROOT" \
PYTHONPATH="$PYTHONPATH" \
DISPLAY=:0 \
"$PYTHON_BIN" \
"$REPO/openpilot/selfdrive/ui/ui.py"
UI 視窗出現後,即可檢查 C4 預設版面的字型、設定頁面、 警示文字及按鈕配置。
十、啟動 C3X/tizi UI 模擬器
C3X 模式與 C4 的主要差異,是啟動時加入:
BIG=1
完整指令:
cd "$REPO"
env \
CEREAL_FAKE=1 \
CEREAL_FAKE_PREFIX="$SIM_PREFIX" \
OPENPILOT_PREFIX="$SIM_PREFIX" \
PARAMS_ROOT="$PARAMS_ROOT" \
PYTHONPATH="$PYTHONPATH" \
BIG=1 \
DISPLAY=:0 \
"$PYTHON_BIN" \
"$REPO/openpilot/selfdrive/ui/ui.py"
如果啟動後看起來仍然是一般 PC/C4 畫面,先確認是否真的傳入:
BIG=1
而不是:
BIG_UI=1
環境變數可能被背景啟動器遺失
如果 UI 是透過 Windows 背景工具或其他 launcher 啟動,
launcher 可能沒有保留 BIG、CEREAL_FAKE 或其他環境變數。
此時可在 Python 載入 UI 之前,直接透過
os.environ.update() 設定環境。
範例:
cd "$REPO"
"$PYTHON_BIN" -c "
import os
import runpy
import sys
repo = os.environ['REPO']
sys.path[:0] = [
repo,
repo + '/opendbc_repo',
repo + '/msgq_repo',
]
os.environ.update({
'CEREAL_FAKE': '1',
'CEREAL_FAKE_PREFIX': os.environ['SIM_PREFIX'],
'OPENPILOT_PREFIX': os.environ['SIM_PREFIX'],
'PARAMS_ROOT': os.environ['PARAMS_ROOT'],
'BIG': '1',
'DISPLAY': ':0',
})
runpy.run_path(
repo + '/openpilot/selfdrive/ui/ui.py',
run_name='__main__',
)
"
Windows 掛載的工作樹特別容易遇到 Python 已經啟動,
但 Repository 路徑尚未加入 sys.path 的情況。
因此必須在 import openpilot 之前加入:
sys.path[:0] = [
repo,
repo + "/opendbc_repo",
repo + "/msgq_repo",
]
十一、同時比較兩個版本
若要同時比較 main 與 test/sp-11.2,
兩個版本必須使用不同路徑、Params 與 Fake prefix。
版本 A:main
REPO=/home/kingchang/openpilot-main
SIM_PREFIX=main
PARAMS_ROOT=/tmp/openpilot-ui-main-params
MSGQ=/dev/shm/msgq_main
版本 B:test/sp-11.2
REPO=/mnt/c/Users/kingchang.ECS/Documents/Codex/2026-07-20/test-sp-11-2-codex-text/work/openpilot
SIM_PREFIX=local_a24
PARAMS_ROOT=/tmp/openpilot-ui-local-a24
MSGQ=/dev/shm/msgq_local_a24
確認第二個 Repository 的版本:
cd /mnt/c/Users/kingchang.ECS/Documents/Codex/2026-07-20/test-sp-11-2-codex-text/work/openpilot
git branch --show-current
git rev-parse HEAD
git status --short --branch
git submodule status opendbc_repo msgq_repo
每個版本都要分別執行:
- 設定自己的環境變數。
- 建立自己的 Params。
- 建立自己的
/dev/shm/msgq_<prefix>。 - 啟動自己的 Fake Publisher。
- 啟動自己的 UI。
這可能造成兩個視窗收到錯誤資料、同時卡在教學頁面, 或產生
MultiplePublishersError。
十二、正確停止與重啟單一模擬器
不要使用:
pkill -f python
pkill -f ui.py
這些指令可能一次關掉其他正在運作的模擬器、Codex 工作或 Python 程序。
1. 找出指定 UI PID
ps -eo pid,args | grep -E 'ui.py|start_ui_publisher.py'
2. 只停止指定程序
kill <UI_PID>
kill <PUBLISHER_PID>
Publisher 應依照自己的 CEREAL_FAKE_PREFIX 與命令列內容辨識,
不要廣泛清除所有 Python process。
3. 重新啟動
重新執行:
- 建立或確認 msgq 目錄。
- 啟動 Fake Publisher。
- 確認
deviceState存在。 - 啟動 C3X 或 C4 UI。
十三、常見問題與處理方式
問題 1:UI process 存在,但沒有視窗
先在 PowerShell 執行:
wsl --shutdown
再重新開啟 Ubuntu 並啟動 Publisher 與 UI。 如果仍無畫面,再完整重新啟動 Windows。
實際上可能發生 WSLg/GPU GUI 狀態失效: Python 程序仍在執行,OpenGL 檢查也可能正常, 但 Windows compositor 不再顯示 Linux 視窗。 這不一定是 openpilot source code 的問題。
問題 2:deviceState 不存在
錯誤可能類似:
deviceState: No such file or directory
依序確認:
- Publisher 是否仍在執行。
/dev/shm/msgq_<prefix>是否存在。- UI 與 Publisher 的 prefix 是否完全一致。
- Publisher log 是否有 Python traceback。
mkdir -p "/dev/shm/msgq_${SIM_PREFIX}"
ls -l "/dev/shm/msgq_${SIM_PREFIX}/deviceState"
cat "/tmp/openpilot-ui-${SIM_PREFIX}-publisher.log"
問題 3:卡在 Driver Monitoring 教學
確認以下項目:
- UI 與 Params 寫入指令使用完全相同的
PARAMS_ROOT。 CompletedTrainingVersion已成功寫入。- Terms 與 SunnyLink consent 已成功寫入。
IsDriverViewEnabled已設為 false。- 沒有誤用另一個模擬器的 Params 目錄。
如果刪除 Params 重新建立,必須再次執行略過教學的 Params 寫入程序。
問題 4:No module named opendbc
確認:
export PYTHONPATH="$REPO:$REPO/opendbc_repo:$REPO/msgq_repo"
若使用 Python -c 或背景啟動器,
必須在 import openpilot 前加入:
sys.path[:0] = [
repo,
repo + "/opendbc_repo",
repo + "/msgq_repo",
]
問題 5:UnknownKeyName
這通常代表 Python 正在載入另一個 branch 或 commit 所編譯的
params_pyx.so。
當新 branch 增加了 Param key,卻沿用舊版原生模組時, 即使 Python source 已更新,原生模組仍可能拒絕該 key。
處理方向:
- 確認目前 branch 與完整 commit SHA。
- 確認 submodule SHA。
- 確認 Python 載入的是目前 Repository。
- 依照目前 commit 重新建置相關原生模組。
不建議直接以手動寫檔方式繞過 Params key 檢查, 因為 UI 讀取端仍可能檢查 key 是否存在。
問題 6:MultiplePublishersError
可能原因:
- 舊 Publisher 尚未關閉。
- 兩個模擬器使用相同 prefix。
- Fake Publisher 發布了
uiDebug。 - 同時執行 replay 與同名 Message Publisher。
每個 UI 使用唯一的 CEREAL_FAKE_PREFIX,
並確認同一組 prefix 只有一個 Publisher。
問題 7:C3X 畫面仍像 C4/PC UI
確認真正使用:
BIG=1
不要使用:
BIG_UI=1
若透過背景 launcher 啟動,改用 Python
os.environ.update(),並確保在載入 UI 前就設定完成。
問題 8:中文字型顯示問號
先確認 Git LFS 資源:
git lfs pull --include="openpilot/selfdrive/assets/**,openpilot/sunnypilot/selfdrive/assets/**"
接著檢查:
- Fork 實際載入的
.ttf、.otf或.fnt。 - 字型檔是否只是 Git LFS pointer 文字檔。
- Bitmap font 的
.fnt與 atlas.png是否成對。 - PC 模擬器與 C3X/C4 實機是否載入同一套字型。
如果電腦與裝置使用不同字型,桌面模擬器的換行、 字寬與版面不能代表實機結果。
問題 9:圖片載入失敗
例如:
horizontal_scroll_indicator.png
always_offroad.png
通常表示 Git LFS 尚未下載:
git lfs pull --include="openpilot/selfdrive/assets/**,openpilot/sunnypilot/selfdrive/assets/**"
問題 10:Wi-Fi Adapter 錯誤
可能看到:
Object path ('T') must start with /
WSL 模擬環境通常沒有裝置端的 NetworkManager 或完整 Wi-Fi adapter, 此錯誤通常不影響 UI 畫面,可以先忽略。
問題 11:SCons 長時間停在 Reading SConscript files
Repository 若位於 /mnt/c,
Windows 檔案系統掃描通常會比 WSL ext4 慢很多。
此外,tinygrad 的 GPU 探測也可能拖慢建置。 不建議直接永久修改 tinygrad source 規避問題。
較適合的長期做法:
- 將 build checkout 放在 WSL ext4。
- 只把截圖、結果或需要分享的檔案放回 Windows。
- 保留各 branch 對應的原生模組與 submodule 狀態。
十四、安全原則
- 模擬環境不可傳送 CAN。
- 不要連接 Panda。
- 不要啟動 controls output。
- 不要修改或直接 push 正式 main branch。
- 不同 UI 不共用 Params。
- 不同 UI 不共用 Fake msgq prefix。
- Fake Publisher 不發布
uiDebug。 - 不要使用全域
pkill關閉其他模擬器。 - 不要提交 Params、log、route、build output 或 screenshot。
- UI 能開只代表桌面渲染成功,不代表車輛功能驗證通過。
十五、每次測試建議記錄的資訊
每次啟動模擬器,建議記錄:
- Repository 絕對路徑。
- Branch 名稱。
- 完整 commit SHA。
opendbc_repoSHA。msgq_repoSHA。PARAMS_ROOT。CEREAL_FAKE_PREFIX。OPENPILOT_PREFIX。- 使用 C3X/tizi 或 C4 模式。
- 是否設定
BIG=1。 - 是否保持未設定
SCALE。 - 字型與 Git LFS assets 是否成功載入。
- UI 是否持續執行,而不是啟動後立即 crash。
- 與 C3X/C4 實機仍有哪些差異。
快速取得版本資訊
cd "$REPO"
git status --short --branch
git rev-parse HEAD
git submodule status opendbc_repo msgq_repo
十六、啟動流程快速摘要
- 安裝 Windows 11、WSL2、Ubuntu 22.04 與 WSLg。
- 準備 openpilot virtual environment。
- Clone 或建立獨立 Git worktree。
- 同步
opendbc_repo與msgq_repo。 - 下載 Git LFS 字型與圖片資源。
- 設定獨立的 Repository、prefix 與 Params 路徑。
- 建立模擬器專用 Params。
- 建立
/dev/shm/msgq_<prefix>。 - 啟動 Fake Message Publisher。
- 確認
deviceState已建立。 - C4 使用預設 UI,不設定
BIG與SCALE。 - C3X/tizi 加入
BIG=1,不要使用BIG_UI=1。 - 最後仍須回到 C3X/C4 bench 與實車驗證。
openpilot UI 桌面模擬器非常適合在修改字型、翻譯、按鈕或設定頁面後, 先快速確認 C3X/C4 的基本排版。
但它沒有 Camera、modeld、Panda、CAN、觸控與實機 GPU, 因此模擬器畫面正常,只能代表 UI 在桌面環境成功渲染, 不能視為車輛控制或裝置相容性已經驗證完成。
文件整理依據:C4_UI_SIMULATOR_WSL2.md、openpilot-ui-simulator-guide.md
留言
張貼留言