用 Wi-Fi 6E(Intel AX211, 160MHz、256 子載波、2 天線)的高維 CSI,做無接觸、免穿戴、匿名的睡眠呼吸中止(OSA/CSA/低通氣)居家篩檢。核心創新是姿態感知子載波選擇(PASS)與分層場域校準,並以物理數位孿生在真實資料到位前驗證整條演算法管線。
學術誠信鐵律:所有合成/模擬結果只驗證相對趨勢與邏輯,AI/模擬估計值絕不可當作真實實驗數據呈現。論文 Table I–IV 的數字必須用真實 AX211 資料重新驗證。
合成端管線已完整、可重現、有 CI 保護;真實端橋接已就緒,等待真實 AX211 資料。
| 面向 | 狀態 |
|---|---|
| 物理合成核心(乾淨/真實化/臨床/多邊形幾何四層) | ✅ 完成 |
| 互動數位孿生 v3(種子可重現 + 複數 CSI 匯出 + MIMO + OFDM 結構) | ✅ 完成 |
| E1 高維靈敏度(AX211 融合 SNR 增益 +8.9 dB) | ✅ 已形式化+測試 |
| C2 / E3 PASS 姿態感知子載波選擇 | ✅ 合成原型+測試 |
| C3 / E4 輕量雙任務模型(<1M 參數 BiLSTM + NumPy 基線) | ✅ 合成原型+測試 |
| E5 跨場域校準 | ✅ 已形式化+測試 |
| 統一基準測試(硬體 × SNR × 姿態 × 真實度) | ✅ 完成 |
| CI(pytest 矩陣 × Python 3.10–3.12 + torch + CSIKit) | ✅ 完成 |
| 真實 CSI 資料管線(CSIKit → 與合成相同的估測管線) | ✅ 骨架就緒,待真實 AX211 資料接入 |
實驗協定(情境分類/檔名/manifest/錄製檢查清單,見 csi_synth/EXPERIMENT_PROTOCOL.md) |
✅ 完成 |
| E2 擷取工具評比、論文 Table I–IV | 🔜 待照協定採集真實資料 |
| 路徑 | 說明 |
|---|---|
csi_synth/csi_synth/ |
物理合成 Python 套件核心:generator/noise/realism/clinical/polygon(四層)+pass_select(C2)+dual_task(C3)+twin_import/realdata(sim↔real 橋接) |
csi_synth/*_analysis.py、plot_*.py |
各實驗腳本(E1 highdim_analysis.py、E5 site_calibration.py、C2 pass_analysis.py、C3 dual_task_analysis.py)+統一基準 benchmark.py+對應繪圖 |
csi_synth/sim_to_real.py |
把真實擷取與合成匯出過同一套估測管線並列比較,輸出 sim-to-real gap |
csi_synth/dual_task_torch.py |
論文 C3 的 <1M 參數 BiLSTM 參考實作(PyTorch,選用相依) |
csi_synth/tests/ |
92 個測試,鎖定每個實驗的科學排序(見下方測試表) |
csi_synth/tools/twin_ui_bench.mjs |
headless 驅動孿生 UI,端到端佐證 Python 基準結果 |
csi-digital-twin-pro.jsx |
互動數位孿生 v3(React):MIMO · 材質多路徑 · 地面反射 · 硬體損傷 · 真實 CSI 採集缺陷 · OFDM 子載波結構 · 整夜睡眠情境 · 種子可重現 · 複數 CSI/情境 JSON 匯出 |
firmware/esp32_csi_sender/ |
ESP32 韌體:固定節奏主動探測取得 CSI,經 UDP 傳到筆電/手機。先讀 firmware/README.md(從零開始的操作步驟) |
csi_synth/tools/csi_monitor.py |
監控+健檢 CLI:listen/validate/resample/schedule,含爆發式成因診斷、空房間對照、估計值穩定性 |
csi_synth/tools/csi_dashboard.py |
即時網頁畫面:子載波瀑布圖 · 取樣品質 · 呼吸頻帶 prominence · 歷史趨勢(純 stdlib,無外部相依) |
android/ |
Android app(CSI Sense):即時 UDP 接收、DEMO 孿生模式,與 Python 共用同一套解析與爆發式判定 |
twin_core/ |
跨語言孿生物理核心(Python 為基準,Kotlin/JS 移植),以黃金向量在 CI 綁住三者一致 |
docs/ |
實驗規劃(01) · 文獻分析與貢獻定位(02) · Posture-Robust 論文草稿(03) · 論文第二章 · 後續章節規劃書 |
csi_synth/deployment/DEPLOYMENT.md |
實際佈署方案 A/B/C/D 比較與架構圖(目前原型走 B,長期目標 C) |
csi_synth/BENCHMARK.md |
統一基準測試報告(偵測門檻、sim-to-real 落差、UI 佐證) |
csi_synth/EXPERIMENT_PROTOCOL.md |
真實資料採集實驗協定:情境分類、檔名/manifest 規範、錄製檢查清單、如何接進 load_real_csi/sim_to_real.py |
AX211_CSI_建置SOP.docx |
硬體/軟體環境建置 SOP |
.github/workflows/ci.yml |
CI:pytest 矩陣(3.10–3.12)+ 選用相依(torch/CSIKit)job |
WiFi_CSI_Sleep_Apnea_Paper_Draft.docx |
英文論文初稿(場域校準+數位孿生敘事;待拆分至 P1/P2) |
WiFi_CSI_*.pptx |
研究簡報(提案/完整/教學版) |
兩篇論文_分工與時程規劃.md |
兩篇分階段策略:資產對照表+時程(建議先讀) |
專案文件_WiFi_CSI_研究紀錄.md |
完整研究、規劃與工作紀錄(接手入口,建議先讀) |
- C1 首次系統評估 AX211 256 子載波 CSI 的生命徵象偵測增益 —— 合成驗證:融合 SNR_eff 比 20MHz 裝置多 +8.9 dB(E1)。
- C2 姿態感知子載波選擇(PASS):翻身偵測 → 姿態指紋分類 → 動態重選敏感子載波 —— 合成驗證:翻身門控降呼吸率誤差 ×2.1,雙天線姿態分類 33%→72%。
- C3 輕量雙任務模型(呼吸率迴歸+呼吸中止分類,<1M 參數)—— 合成驗證:呼吸率 MAE 1.4 BPM,救回動作型偵測完全漏掉的低通氣/OSA。
- C4 分層場域校準(通用底層/場域校準/姿態自適應)+與 PSG 臨床比對 —— 合成驗證:通用 2.11→場域專屬 0.47 BPM(E5)。
- C5 FeitCSI/IAX 擷取工具於 AX211 的訊號品質評比 —— 待真實資料(E2)。
cd csi_synth
pip install -r requirements.txt
pytest tests/ -v # 92 個測試(torch/CSIKit 為選用相依,未裝則自動 skip)
python benchmark.py # 統一基準:硬體 × SNR × 姿態 × 真實度
python pass_analysis.py # C2 PASS 消融
python dual_task_analysis.py # C3 雙任務模型
python demo_visualize.py # 產生示意圖真實資料接入(採到 AX211 擷取後):
from csi_synth import load_real_csi, estimate_rate
res = load_real_csi("capture.dat") # FeitCSI/AX211 自動辨識(需 pip install csikit)
print(estimate_rate(res, band=(0.1, 0.6))["bpm"])或用 python sim_to_real.py capture.dat --truth-bpm 15 直接產出 sim-to-real 對比報表。
手機開熱點 → ESP32 收 CSI → UDP 傳到筆電。完整步驟見 firmware/README.md,摘要:
# 1. 燒錄 firmware/esp32_csi_sender/,改掉最上方的 SSID / 密碼 / 筆電 IP
# 2. 筆電開監控
cd csi_synth
python tools/csi_monitor.py listen --port 5566 --expect-subcarriers 64
# 3. 正式錄一段(寫出的就是分析管線直接讀得懂的格式)
python tools/csi_monitor.py listen --port 5566 --out real_data/pilot/S01.csv --seconds 300
# 4. 事後複查(FAIL 時離開碼為 1)
python tools/csi_monitor.py validate real_data/pilot/S01.csv
# 5. 若判定為 jitter(封包都在、只是間隔在抖):重取樣成均勻網格
python tools/csi_monitor.py resample real_data/pilot/S01.csv --hz 10 --out S01_uniform.csv
# 6. 無人看管的長時間錄製(每 10 分鐘錄 60 秒,附 summary.csv 趨勢表)
python tools/csi_monitor.py schedule --out-dir real_data/unattended --hours 6
# 7. 即時畫面(瀑布圖/取樣品質/呼吸頻帶/歷史趨勢)→ http://127.0.0.1:8099
python tools/csi_dashboard.py --port 5566 --illuminate <ESP32的IP>數位孿生的「實機 LIVE」模式:用瀏覽器開 repo 根目錄的 csidigitaltwinpro.html
(csi-digital-twin-pro.jsx 打包後的成品),右上角可切換 模擬 / 實機 LIVE。
這跟 127.0.0.1:8099 是兩個不同畫面——8099 是 dashboard 自己的頁面,上面沒有切換鈕。
切到實機後,孿生介面會向上面那支 dashboard 拉真實訊框,然後跑同一個 runDetection()——
就是模擬情境用來評分的那一個。合成資料上調出來的偵測器,如果沒在真實訊號上跑過,等於沒被測過。
實機模式下會強制講清楚三件事(否則畫面會說謊):
- 沒有真值可比對 → 不顯示 ✓/準確率,只顯示「待驗證的輸出」。要準確率得另外錄已知答案的對照。
- 取樣不均勻就不給 bpm →
Δt cv > 0.5時直接顯示「⚠ 取樣不可用」。這正是當初那個假 6 bpm 的來源。 - 模擬設定全部停用 → 牆材質、干擾情境那些只作用於合成;真實訊號要改,只能移動人/裝置。
踩到的坑(已修):
runDetection的門檻(ACT_HI=0.011)是絕對值,用模擬的振幅尺度定的; ESP32 送的是 AGC 相關的原始整數(~22),算出來 act≈0.10,是門檻的 9 倍—— 任何真實訊號都會被判成「移動」。修法是把整幀除以一個 60 秒長時窗的平均值, 換成「以平均振幅為單位」。這是單位換算不是調參:子載波之間的關係完全不變。 時窗一定要長,短的會把呼吸本身平均掉。(治不了的:AGC 突跳仍會被當成一次移動。)
取樣節奏改由筆電主導。 韌體原本 ping AP、在回覆上量 CSI,等於每個樣本的時間都 押在手機的往返延遲上——而手機會批次化並限制 ICMP。實測長間隔在每一個 60 秒視窗都 集中在 ~1.0 秒間距,那是 AP 的週期行為,不是房間裡的人。改用
--illuminate由筆電單向送 UDP:實測自身節奏 cv 0.0084(對比 ping 路徑的 0.59–0.79)。 不需要改韌體也不必重燒——CSI 是在封包「被接收」時就量到的,早於任何埠的處理。
錄之前先看一眼。
real_data/second_batch_20260722/那批資料在分析階段才發現取樣是 爆發式的(中位數看似 125 Hz、有效只有 66 Hz),呼吸峰因此被擠到頻帶邊緣、估出假的 ~6 bpm。 監控工具會在幾秒內就把這件事講出來。均勻比快重要——乾淨的 20 Hz 勝過爆發式的 125 Hz。
而重取樣救不回已經壞掉的資料。 上面那批重取樣後每一項檢查都 PASS, 但估計值在 6/10/12/20 Hz 網格上是 22.2/25.1/15.7/18.2 bpm——答案取決於一個任意的 處理選擇,那就不是量測。所以
resample會把均勻度標成BY CONSTRUCTION(它必定通過, 因此沒有鑑別力),改用estimate stability判斷,並在內插比例過高時直接拒絕執行。 詳見研究紀錄 §2.23。
每次錄製都要配一段空房間對照組。 這是唯一能分辨「偵測到」與「假象」的檢查。 在本專案自己的第二批資料上,空房間的「呼吸訊號」比真人還強(51.2 dB vs 21.4 dB)—— 空房間不會呼吸,所以那個峰必然是採樣假象。所有單檔檢查對兩者都是 PASS,只有對照比較會 FAIL:
python tools/csi_monitor.py validate S01_person.csv --baseline S01_empty.csv現況(誠實):兩批真實資料都沒有可用的呼吸訊號,Table I–IV 尚無真實資料可填。詳見 §2.24。
- 本 repo 之程式與文件為 DofLab 研究產出。
- 第三方學術論文 PDF 不隨附(見
.gitignore),請自行由原出版方取得。 - 尚未包含真實 AX211 量測資料;所有模擬數字為模型相對值,非量測,投稿前須用真實資料重新驗證。
DofLab · 國立勤益科技大學 · 智慧自動化工程系