WiFi CSI穿墙检测:SDR自适应PCA框架及其在座舱感知中的应用启示

发布时间: 2026-09-16
标签: WiFi CSI, SDR, 穿墙检测, PCA, 小波变换, 座舱感知, CPD, Bluebottle


论文信息

项目 详情
标题 Through-Wall Detection using Software-Defined Radio based on adaptive Principal Component Analysis
arXiv 2609.12443
作者 Dinuli Naotunna et al.
提交日期 2026-09-11
页数 15页, 7图
领域 eess.SP (Signal Processing)

核心创新

本文提出了一种不依赖受控接入点或专用硬件的WiFi CSI穿墙检测系统,使用定制SDR(Bluebottle)从环境WiFi包中提取CSI。关键创新在于频谱域自适应主成分选择机制

  1. 从PCA分解的各主成分中,使用Welch功率谱密度估计量化每个成分的信噪比和人体运动频段的频谱集中度
  2. 自动选择与运动最相关的主成分
  3. 通过连续小波变换(CWT)实现时间局部化运动事件检测

与现有方法的区别

方法 接入点要求 PCA选择策略 检测方式 硬件成本
传统TWD 需受控AP 固定前N个成分 STFT 高(专用设备)
本文方法 无需受控AP 自适应频谱评分 CWT小波 低(SDR接收)

技术详解

1. CSI信号模型

WiFi信号穿墙后,CSI模型为:

$$H(f_k, t) = e^{-j2\pi\Delta f t} \left( H_s(f_k, t) + H_d(f_k, t) \right)$$

其中:

  • $H_s(f_k, t)$ = 静态路径CSI(墙壁、家具等静止物体)
  • $H_d(f_k, t)$ = 动态路径CSI(人体运动引起)
  • $\Delta f$ = 收发端载波频差
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
import numpy as np
from typing import Tuple
from scipy.signal import welch, find_peaks

def extract_csi_features(
csi_data: np.ndarray,
fs: float = 100.0,
motion_band: Tuple[float, float] = (0.5, 3.0)
) -> dict:
"""
从CSI数据中提取运动特征

论文核心算法复现:自适应PCA主成分选择

Args:
csi_data: CSI矩阵, shape=(n_subcarriers, n_samples)
fs: 采样率(Hz)
motion_band: 人体运动频段(Hz)
- 0.5-3 Hz: 呼吸/心跳微动
- 3-10 Hz: 肢体运动

Returns:
包含选择的主成分和检测结果的字典

参考:
Naotunna et al., "Through-Wall Detection using SDR
based on adaptive PCA", arXiv:2609.12443, 2026
"""
n_subcarriers, n_samples = csi_data.shape

# Step 1: PCA分解
from sklearn.decomposition import PCA
pca = PCA(n_components=min(10, n_subcarriers))
components = pca.fit_transform(csi_data.T) # shape=(n_samples, n_components)

# Step 2: 计算每个主成分的频谱评分
scores = []
for i in range(components.shape[1]):
# Welch功率谱密度估计
freqs, psd = welch(
components[:, i],
fs=fs,
nperseg=min(256, len(components[:, i]))
)

# 计算运动频段能量占比
motion_mask = (freqs >= motion_band[0]) & (freqs <= motion_band[1])
motion_energy = np.sum(psd[motion_mask])
total_energy = np.sum(psd)

# 频谱集中度评分
if total_energy > 0:
spectral_score = motion_energy / total_energy
else:
spectral_score = 0

# 信噪比估计
noise_band = (freqs >= 10) & (freqs <= 20) # 噪声频段
noise_power = np.mean(psd[noise_band]) if np.any(noise_band) else 1e-10
snr = motion_energy / noise_power

scores.append({
'component_idx': i,
'spectral_score': float(spectral_score),
'snr': float(snr),
'motion_energy': float(motion_energy),
'explained_variance': float(pca.explained_variance_ratio_[i])
})

# Step 3: 选择频谱评分最高的主成分
scores.sort(key=lambda x: x['spectral_score'], reverse=True)
best_component_idx = scores[0]['component_idx']
best_signal = components[:, best_component_idx]

# Step 4: 连续小波变换(CWT)检测时间局部化运动
import pywt
scales = np.arange(1, 64)
wavelet = 'morl' # Morlet小波

coeffs, freqs_cwt = pywt.cwt(best_signal, scales, wavelet, 1.0/fs)
energy = np.abs(coeffs)

# 检测运动事件(能量峰值)
energy_sum = np.sum(energy, axis=0)
threshold = np.mean(energy_sum) + 2 * np.std(energy_sum)
peaks, _ = find_peaks(energy_sum, height=threshold, distance=int(fs*0.5))

return {
'motion_detected': len(peaks) > 0,
'n_events': len(peaks),
'event_times': peaks / fs,
'best_component': best_component_idx,
'spectral_scores': scores,
'energy_profile': energy_sum.tolist(),
'detection_threshold': float(threshold)
}


def simulate_cabin_csi(
n_subcarriers: int = 56,
duration_s: float = 10.0,
fs: float = 100.0,
breathing_rate: float = 0.3,
motion_events: list = None
) -> np.ndarray:
"""
模拟座舱内CSI数据(含人体微动)

Args:
n_subcarriers: WiFi子载波数
duration_s: 持续时间(秒)
fs: 采样率(Hz)
breathing_rate: 呼吸频率(Hz), 婴儿~0.3-1.0
motion_events: 运动事件列表 [(start_s, duration_s, amplitude)]

Returns:
csi_data: shape=(n_subcarriers, n_samples)
"""
n_samples = int(duration_s * fs)
t = np.linspace(0, duration_s, n_samples)

if motion_events is None:
motion_events = [(2.0, 3.0, 0.5)] # 默认2秒开始,持续3秒

# 静态路径(墙壁/座椅等)
static_csi = np.exp(1j * 2 * np.pi * 0.1 * np.random.randn(n_subcarriers))
csi = np.zeros((n_subcarriers, n_samples), dtype=complex)

for k in range(n_subcarriers):
# 静态分量
csi[k, :] = static_csi[k]

# 动态分量:呼吸微动
breathing = 0.01 * np.sin(2 * np.pi * breathing_rate * t)
csi[k, :] += breathing * np.exp(-1j * 2 * np.pi * k * 0.01)

# 运动事件
for start, dur, amp in motion_events:
mask = (t >= start) & (t <= start + dur)
motion = amp * np.random.randn(np.sum(mask))
csi[k, mask] += motion * np.exp(-1j * 2 * np.pi * k * 0.05)

# 添加噪声
noise = 0.01 * (np.random.randn(*csi.shape) + 1j * np.random.randn(*csi.shape))
csi += noise

return csi


if __name__ == "__main__":
print("=== WiFi CSI 穿墙/座舱感知检测仿真 ===\n")

# 模拟座舱场景:后排有儿童呼吸(微动)
np.random.seed(42)

# 场景1: 有人(呼吸微动 + 偶发运动)
print("[场景1] 后排有儿童(呼吸频率0.4Hz)")
csi_with_person = simulate_cabin_csi(
n_subcarriers=56,
duration_s=10.0,
fs=100.0,
breathing_rate=0.4,
motion_events=[(3.0, 1.0, 0.3), (6.5, 0.5, 0.2)]
)
result1 = extract_csi_features(csi_with_person, fs=100.0, motion_band=(0.3, 3.0))
print(f" 运动检测: {result1['motion_detected']}")
print(f" 检测到 {result1['n_events']} 个运动事件")
print(f" 最佳主成分: PC{result1['best_component']}")
print(f" 频谱评分: {result1['spectral_scores'][0]['spectral_score']:.4f}")
print(f" 事件时刻: {[f'{t:.2f}s' for t in result1['event_times']]}")

# 场景2: 空座(仅噪声)
print("\n[场景2] 空座(无人体微动)")
csi_empty = simulate_cabin_csi(
n_subcarriers=56,
duration_s=10.0,
fs=100.0,
breathing_rate=0.0,
motion_events=[]
)
result2 = extract_csi_features(csi_empty, fs=100.0, motion_band=(0.3, 3.0))
print(f" 运动检测: {result2['motion_detected']}")
print(f" 检测到 {result2['n_events']} 个运动事件")
print(f" 最佳主成分: PC{result2['best_component']}")
print(f" 频谱评分: {result2['spectral_scores'][0]['spectral_score']:.4f}")

2. 自适应PCA选择算法

传统方法固定选择前N个主成分,但前面的主成分可能主要包含静态多径而非运动信息:

graph LR
    A[原始CSI<br/>56子载波 x N样本] --> B[PCA分解<br/>10个主成分]
    B --> C{自适应频谱评分}
    C --> D["计算每个PC的<br/>Welch PSD"]
    D --> E["运动频段能量<br/>(0.5-3 Hz)"]
    E --> F["频谱集中度<br/>= 运动能量/总能量"]
    F --> G[排序选择<br/>Top-K成分]
    G --> H[小波变换<br/>时间局部化]
    H --> I{运动事件检测}
    
    style C fill:#fa0
    style G fill:#9f9

3. 与传统PCA的对比

对比项 传统PCA 自适应PCA
成分选择 固定前N个 频谱评分排序
噪声鲁棒性 弱(前几个成分可能被静态路径主导) 强(选择运动相关成分)
误检率
时频分辨率 STFT(有限) CWT(高分辨率)
AP控制 需要受控AP 无需AP控制
硬件 专用设备 SDR(低成本)

4. Bluebottle SDR

特性 规格
类型 定制软件定义无线电
功能 从环境WiFi包提取CSI
AP控制 不需要
频段 2.4 GHz / 5 GHz WiFi
成本 远低于专用MIMO设备

座舱感知应用映射

从穿墙检测到CPD的技术映射

穿墙检测概念 座舱感知对应 说明
墙壁 座椅靠背/头枕 WiFi信号穿透障碍
人体运动 儿童呼吸/心跳 0.3-3 Hz微动频段
CSI多径 座舱多径环境 金属车身+多座椅
穿墙检测 CPD儿童检测 非接触式生命体征
SDR接收 车载WiFi模块 复用现有WiFi硬件

座舱WiFi感知架构

graph TB
    subgraph "座舱WiFi CSI感知系统"
        A[车载WiFi AP<br/>2.4/5 GHz] --> B[WiFi信号传播]
        B --> C[多径反射<br/>座椅/车身/人体]
        C --> D[WiFi接收端<br/>SDR或WiFi芯片]
        D --> E[CSI提取]
        E --> F[自适应PCA<br/>频谱评分选择]
        F --> G[小波变换<br/>微动检测]
        G --> H{CPD判定}
        H -->|有人| I[儿童存在<br/>触发警报]
        H -->|无人| J[空座]
    end
    
    style A fill:#4a9
    style I fill:#f99

竞品与技术路线对比

方案 感知介质 成本 分辨率 隐私 NLoS能力
WiFi CSI (本文) WiFi信号 极低(复用车载WiFi) 低(呼吸级) ✅ 无摄像头 ✅ 穿透座椅
mmWave 60GHz 毫米波雷达 中($5-15) 高(cm级) ⚠️ 座椅穿透有限
UWB 802.15.4ab UWB脉冲 中($3-10) 中(5cm级)
红外摄像头 红外图像 高($30-80) 极高 ⚠️ 需隐私处理 ❌ 需视距
压力传感器 压力阵列 低($2-5) ❌ 仅座椅接触

IMS开发启示

1. WiFi CSI作为CPD补充方案

WiFi CSI感知的最大价值在于零增量硬件成本——复用车载WiFi模块即可实现CPD辅助检测:

优势 说明
零硬件增量 复用车载WiFi AP/STA
全座舱覆盖 WiFi信号覆盖所有座椅
隐私友好 无摄像头,无图像采集
穿透能力强 穿透座椅靠背、毯子
劣势 说明
分辨率低 仅检测呼吸级微动,无法定位
金属座舱干扰 车身金属反射复杂多径
环境依赖 需要WiFi信号稳定
无法分类 无法区分儿童/宠物/物品

2. 多传感器融合建议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# WiFi CSI + UWB雷达 + 压力传感器融合CPD方案
class MultiSensorCPD:
"""
多传感器融合CPD系统

层级1: WiFi CSI(粗筛 - 是否有人)
层级2: UWB雷达(细判 - 位置/呼吸)
层级3: 压力传感器(确认 - 重量分类)
"""

def __init__(self):
self.wifi_threshold = 0.5 # WiFi CSI检测阈值
self.uwb_threshold = 0.7 # UWB检测阈值
self.pressure_min_kg = 2.5 # 最小重量(kg)判断有生命体

def detect(self, wifi_result: dict, uwb_result: dict, pressure_kg: float) -> dict:
"""
三级融合CPD检测

Args:
wifi_result: WiFi CSI检测结果
uwb_result: UWB雷达检测结果
pressure_kg: 座椅压力传感器读数(kg)

Returns:
融合判定结果
"""
# 层级1: WiFi CSI粗筛
wifi_confidence = wifi_result.get('confidence', 0)
if wifi_confidence > self.wifi_threshold:
# 层级2: UWB细判
uwb_confidence = uwb_result.get('confidence', 0)
if uwb_confidence > self.uwb_threshold:
# 层级3: 压力确认
if pressure_kg > self.pressure_min_kg:
return {
'detected': True,
'confidence': 0.95,
'classification': 'child' if pressure_kg < 30 else 'adult',
'method': 'wifi+uwb+pressure',
'breathing': uwb_result.get('breathing_rate', 0)
}

return {
'detected': False,
'confidence': 0.3,
'method': 'multi-sensor-fusion'
}

3. 部署优先级

优先级 应用 技术成熟度 时间线
🟡 P1 CPD辅助检测(零成本WiFi粗筛) TRL 4-5 2027 Q3
🟢 P2 生命体征监测(呼吸频率) TRL 3-4 2028+
🟢 P2 座椅占用检测(WiFi+压力融合) TRL 5 2027 Q4
🔴 P0 与UWB 802.15.4ab融合方案 TRL 2-3 2028+

结论

本文的自适应PCA框架为WiFi CSI感知提供了更鲁棒的信号处理基础:

  1. 自适应成分选择 — 通过频谱评分自动识别运动相关主成分
  2. 小波时频分析 — CWT提供比STFT更高的时频分辨率
  3. 零AP控制 — SDR从环境WiFi被动提取CSI
  4. 座舱应用映射 — WiFi CSI可作为CPD的零成本补充方案

对IMS开发的核心启示: WiFi CSI感知虽然分辨率有限,但作为CPD的”零成本粗筛”层具有独特价值。建议构建WiFi CSI → UWB → 压力的三级检测级联,降低对单一传感器的依赖。


WiFi CSI穿墙检测:SDR自适应PCA框架及其在座舱感知中的应用启示
https://dapalm.com/2026/09/16/2026-09-16-wifi-csi-twd-sdr-adaptive-pca-cabin-sensing-ims/
作者
Mars
发布于
2026年9月16日
许可协议