mmMind:教基础模型读懂毫米波雷达——雷达-语言模型驱动的座舱行为理解与 IMS 启示

当 LLM 需要感知物理环境中的人体行为,摄像头有隐私风险、穿戴设备依赖用户配合,mmWave 雷达成为隐私友好、非接触、低成本的第三选择。mmMind 首次用 3D 姿态引导的雷达表征学习 + LLM 对齐,实现了纯雷达输入的行为描述、时空问答和未见动作泛化。

论文信息

项目 内容
标题 Teaching Foundation Models to Read mmWave: Pose-Guided Kinematic Representation for Human Behavior Understanding
作者 Duo Zhang, Zhehui Yin, Zhiyun Yao, Haotong Qin, Xusheng Zhang, Hongliu Yang, Jianyu Sun, Junzhe Wang, Zizhou Fan, Michele Magno, Daqing Zhang
机构 北京大学 / ETH Zurich / 巴黎综合理工学院
arXiv 2608.04127
版本 v2, 2026-08-09
代码/演示 项目页 / YouTube Demo

核心创新

mmMind 解决了两个耦合挑战:

  1. 运动学表征挑战:将稀疏雷达点云转化为保留人体骨架结构和运动演化的连续 token
  2. 真实世界雷达-语言对齐挑战:构建首个大规模真实世界 mmWave-语言基准 mmMind-Bench

关键设计:姿态引导的运动学 tokenization

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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
"""
mmMind 核心架构复现

论文 Section 3: Pose-Guided Kinematic Representation Learning
- 训练阶段:3D 姿态监督 → 雷达编码器学习运动学表征
- 推理阶段:移除姿态头,纯雷达输入 → 连续运动学 token → LLM 对齐
"""

import torch
import torch.nn as nn
from typing import Tuple

class SpatioTemporalRadarEncoder(nn.Module):
"""
时空雷达点云编码器

输入:雷达点云序列 (B, T, N, F)
- B: batch size
- T: 时间帧数(5秒 clips, 75帧 @ 15fps)
- N: 每帧点数(最多192个点, 3帧聚合)
- F: 点特征维度 (x, y, z, intensity, vx, vy, vz = 7)

输出:连续运动学 token (B, T, D)
- D: token 嵌入维度
"""

def __init__(
self,
point_dim: int = 7,
hidden_dim: int = 256,
token_dim: int = 512,
num_heads: int = 8,
num_layers: int = 4
):
super().__init__()

# 逐点特征提取
self.point_mlp = nn.Sequential(
nn.Linear(point_dim, hidden_dim),
nn.GELU(),
nn.Linear(hidden_dim, hidden_dim),
nn.GELU()
)

# 空间注意力(帧内)
self.spatial_attn = nn.MultiheadAttention(
embed_dim=hidden_dim,
num_heads=num_heads,
batch_first=True
)

# 时序 Transformer(帧间)
temporal_layer = nn.TransformerEncoderLayer(
d_model=hidden_dim,
nhead=num_heads,
dim_feedforward=hidden_dim * 4,
batch_first=True
)
self.temporal_encoder = nn.TransformerEncoder(
temporal_layer, num_layers=num_layers
)

# 投影到 token 维度
self.proj = nn.Linear(hidden_dim, token_dim)

def forward(
self,
radar_points: torch.Tensor,
point_mask: torch.Tensor = None
) -> torch.Tensor:
"""
Args:
radar_points: (B, T, N, F) 雷达点云
point_mask: (B, T, N) 有效点掩码

Returns:
kinematic_tokens: (B, T, D) 运动学 token
"""
B, T, N, F = radar_points.shape

# 逐点 MLP
x = self.point_mlp(radar_points) # (B, T, N, H)

# 帧内空间注意力
x = x.view(B * T, N, -1) # (B*T, N, H)
x, _ = self.spatial_attn(x, x, x, key_padding_mask=point_mask)

# 帧级池化
x = x.mean(dim=1) # (B*T, H)
x = x.view(B, T, -1) # (B, T, H)

# 时序 Transformer
x = self.temporal_encoder(x) # (B, T, H)

# 投影
tokens = self.proj(x) # (B, T, D)

return tokens


class PoseHead(nn.Module):
"""
3D 姿态预测头(仅训练阶段使用)

监督信号:同步的 3D 姿态序列
训练后移除,推理时仅用雷达编码器
"""

def __init__(self, token_dim: int = 512, num_joints: int = 17):
super().__init__()
self.joint_predictor = nn.Sequential(
nn.Linear(token_dim, token_dim // 2),
nn.GELU(),
nn.Linear(token_dim // 2, num_joints * 3) # 3D 坐标
)

def forward(self, tokens: torch.Tensor) -> torch.Tensor:
"""
Args:
tokens: (B, T, D)
Returns:
poses: (B, T, J, 3)
"""
B, T, D = tokens.shape
poses = self.joint_predictor(tokens) # (B, T, J*3)
poses = poses.view(B, T, -1, 3) # (B, T, J, 3)
return poses


class PoseGuidedPretrainLoss(nn.Module):
"""
姿态引导预训练损失

组合:
1. 关节位置 MSE 损失
2. 运动学一致性损失(速度平滑)
3. 对比损失(增强鲁棒性)
"""

def __init__(self, lambda_vel: float = 0.1, lambda_contrast: float = 0.05):
super().__init__()
self.lambda_vel = lambda_vel
self.lambda_contrast = lambda_contrast

def forward(
self,
pred_poses: torch.Tensor, # (B, T, J, 3)
gt_poses: torch.Tensor, # (B, T, J, 3)
tokens: torch.Tensor # (B, T, D)
) -> Tuple[torch.Tensor, dict]:
# 位置损失
pos_loss = nn.functional.mse_loss(pred_poses, gt_poses)

# 速度一致性损失
pred_vel = pred_poses[:, 1:] - pred_poses[:, :-1]
gt_vel = gt_poses[:, 1:] - gt_poses[:, :-1]
vel_loss = nn.functional.mse_loss(pred_vel, gt_vel)

# 对比损失(同一序列不同增强应相似)
B = tokens.shape[0]
if B > 1:
sim = torch.cosine_similarity(
tokens[::2].flatten(1),
tokens[1::2].flatten(1),
dim=-1
)
contrast_loss = -sim.mean()
else:
contrast_loss = torch.tensor(0.0, device=tokens.device)

total = pos_loss + self.lambda_vel * vel_loss + self.lambda_contrast * contrast_loss

return total, {
'pos_loss': pos_loss.item(),
'vel_loss': vel_loss.item(),
'contrast_loss': contrast_loss.item()
}


class mmMindModel(nn.Module):
"""
完整 mmMind 模型

训练阶段:
radar → encoder → pose_head → loss(3D姿态监督)

推理阶段:
radar → encoder → projector → LLM → 行为描述/问答
"""

def __init__(self, llm_dim: int = 4096):
super().__init__()
self.encoder = SpatioTemporalRadarEncoder()

# 训练阶段使用
self.pose_head = PoseHead()
self.pretrain_loss = PoseGuidedPretrainLoss()

# 推理阶段使用
self.projector = nn.Sequential(
nn.Linear(512, llm_dim),
nn.GELU(),
nn.Linear(llm_dim, llm_dim)
)

def train_forward(self, radar_points, gt_poses, point_mask=None):
"""训练前向"""
tokens = self.encoder(radar_points, point_mask)
pred_poses = self.pose_head(tokens)
loss, metrics = self.pretrain_loss(pred_poses, gt_poses, tokens)
return loss, metrics

def inference_forward(self, radar_points, llm, point_mask=None):
"""推理前向(纯雷达输入)"""
tokens = self.encoder(radar_points, point_mask)
projected = self.projector(tokens)

# 将运动学 token 注入 LLM
# 这里用伪 LLM 接口示意
# 实际实现中通过 cross-attention 或 prefix tuning
behavior_text = llm.generate(
inputs_embeds=projected,
max_new_tokens=128
)
return behavior_text


# ============ 测试代码 ============
if __name__ == "__main__":
torch.manual_seed(42)

# 模拟雷达点云输入 (B=2, T=75, N=192, F=7)
radar_input = torch.randn(2, 75, 192, 7)

# 模拟 3D 姿态 GT (B=2, T=75, J=17, 3)
pose_gt = torch.randn(2, 75, 17, 3)

# 训练模式
model = mmMindModel(llm_dim=4096)
loss, metrics = model.train_forward(radar_input, pose_gt)
print(f"训练损失: {loss.item():.4f}")
print(f" 位置: {metrics['pos_loss']:.4f}")
print(f" 速度: {metrics['vel_loss']:.4f}")
print(f" 对比: {metrics['contrast_loss']:.4f}")

# 验证编码器输出维度
tokens = model.encoder(radar_input)
print(f"\n运动学 token 形状: {tokens.shape}")
print(f" B={tokens.shape[0]}, T={tokens.shape[1]}, D={tokens.shape[2]}")

mmMind-Bench 数据集

指标 数值
总录制时长 17.9 小时
参与者数 23 人(21-62岁)
室内场景数 7 个
行为类别 27 种
Clip 长度 5 秒(75帧 @ 15fps)
雷达设备 商用 60GHz + 77GHz
标注 双语语言标注 + 3D姿态 + 时空QA + 多轮对话

行为覆盖

类别 具体行为
日常活动 行走、坐下、弯腰、使用电脑、躺下、扫地、慢跑、跌倒、喝水、使用手机
运动 仰卧起坐、深蹲、开合跳、跳绳、拳击
上身手势 推、拉、画圈、垂直手部运动

数据采集硬件

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
# mmMind-Bench 数据采集配置
data_config = {
"radar_devices": {
"60GHz": "TI IWR6843AGR (商用开发板)",
"77GHz": "TI AWR1843 (车载级)"
},
"frame_rate": "15 Hz",
"points_per_frame": "up to 64 (CFAR)",
"superframe": "3帧聚合 → 192 points",
"point_features": ["x", "y", "z", "intensity", "vx", "vy", "vz"], # 7维
"clip_length": "5 seconds = 75 frames",
"rgb_d": "用于语言标注(训练后移除)",
"pose_gt": "3D骨骼关节坐标(训练后移除)",
"synchronization": "硬件触发同步"
}

# 信号处理管道
signal_pipeline = """
原始ADC数据
→ Range-Doppler FFT
→ CFAR 检测(保留 ≤64 点/帧)
→ 3帧聚合(superframe, ≤192 点)
→ 坐标变换到统一外参系
→ 运动学 token 提取
"""

实验结果

主要性能指标

任务 指标 mmMind 最佳基线 提升
行为描述 BERTScore 86.8 81.2 (RadarLLM) +5.6
时空问答 准确率 89.2% 82.5% (mmExpert) +6.7%
未见动作泛化 准确率 91.2% 84.3% (mmCLIP) +6.9%

消融实验

变体 BERTScore QA准确率 说明
完整模型 86.8 89.2% 姿态引导 + LLM对齐
无姿态引导 82.1 85.3% 直接用雷达编码器
离散VQ token 83.5 86.1% 用 VQ-VAE 替代连续token
仅60GHz 85.2 88.0% 移除77GHz数据
仅77GHz 84.6 87.2% 移除60GHz数据

与现有雷达-语言方法对比

方法 表征方式 数据 描述 QA 泛化
mmWave-QA 文本化雷达观测 无训练 ✗ ✗ ✗
mmExpert 2D微多普勒谱 合成 ✓ ✗ ✗
RadarLLM 离散运动码 (VQ-VAE) 合成 ✓ ✗ ✗
mmMind 连续运动学token 真实+合成 ✓ ✓ ✓

架构图

IMS 开发启示

1. CPD 儿童检测:雷达-语言模型直接可用

1
2
3
4
5
6
7
8
9
10
11
# CPD 场景:检测后排是否有儿童/婴儿
cpd_scenario = {
"sensor": "TI AWRL6432 60GHz", # 已量产低成本雷达
"mount": "车顶/B柱内侧",
"input": "雷达点云序列",
"mmMind_task": "行为描述 → '检测到后排小型人体,处于坐姿/躺姿'",
"qa": "Q: 后排是否有人? A: 是,检测到约80cm高度的人体反射",
"advantage": "无需摄像头,隐私友好,支持夜间",
"challenge": "车内多径干扰需要专门处理",
"deployment": "模型量化到INT8,Hexagon NPU部署"
}

2. OOP 异常姿态:运动学 token 直接编码姿态

1
2
3
4
5
6
7
8
9
# OOP 场景:检测乘员是否处于异常坐姿
oop_detection = {
"normal_states": ["正常坐姿", "前倾", "后仰", "左倾", "右倾"],
"abnormal_states": ["跪姿", "蹲姿", "趴在仪表盘", "伸出手窗外"],
"approach": "运动学token → 轻量分类器",
"accuracy_target": ">95%(4类正常 vs 异常)",
"latency": "<100ms(5秒clip处理)",
"hardware": "QCS8255 Hexagon NPU, INT8量化"
}

3. 认知分心:行为序列理解

1
2
3
4
5
6
7
8
9
10
11
# 认知分心:通过行为序列推断注意力状态
cognitive_distraction = {
"indicators": [
"长时间静止(走神)",
"频繁微小调整(焦虑)",
"手势减少(注意力下降)",
"头部朝向变化频率降低"
],
"mmMind_advantage": "LLM可以做时序推理,不只是分类",
"example_qa": "Q: 驾驶员过去30秒行为模式? A: 头部运动减少,手部活动降低,疑似注意力下降"
}

4. 多传感器融合架构

5. 部署优先级排序

优先级 功能模块 技术路线 硬件 预计精度 预计延迟
🔴 P0 CPD 儿童检测 mmMind编码器 → 二分类 TI AWRL6432 >98% <200ms
🔴 P0 OOP 异常姿态 运动学token → 5分类 TI AWRL6432 >95% <100ms
🟡 P1 乘员计数 雷达点云聚类 TI IWR6843 >95% <50ms
🟡 P1 手势识别 mmMind完整模型 TI IWR6843 + NPU >90% <500ms
🟢 P2 行为描述 mmMind + LLM QCS8255 - <1s
🟢 P2 认知分心 时序行为推理 QCS8255 + 云端 - <2s

技术路线建议

短期(3个月内)

  1. 复现 mmMind 编码器:在现有 TI 雷达平台上部署 SpatioTemporalRadarEncoder
  2. 构建车内数据集:在实车内采集 60GHz 雷达 + 同步 3D 姿态(用 Azure Kinect 做 GT)
  3. CPD 二分类:用运动学 token 训练有人/无人二分类器

中期(6个月)

  1. OOP 五分类:正常坐/前倾/后仰/左倾/右倾 → 扩展到跪姿/趴姿
  2. 多雷达部署:车顶 + B柱 + 后视镜三位置,覆盖前后排
  3. 轻量化部署:INT8 量化,模型 <2MB,Hexagon NPU 运行

长期(12个月)

  1. 雷达-语言 LLM 部署:在 QCS8255 上运行完整 mmMind + 轻量 LLM
  2. 多模态融合:雷达 token + 眼动 + 面部 → 统一 LLM 理解
  3. 座舱行为理解:从分类到描述,支持自然语言交互

参考文献

  1. mmMind 论文: arXiv:2608.04127
  2. 项目页: https://duo-zhang-sensing.github.io/mmMind/
  3. mmMind-Bench: 17.9h, 23人, 7场景, 27行为
  4. RadarLLM (基线): 合成数据 + VQ-VAE 离散码
  5. mmExpert (基线): 2D 微多普勒谱
  6. mmCLIP (基线): 对比学习开放词汇

发布时间: 2026-08-25 04:00
标签: mmWave, 雷达感知, LLM, CPD, OOP, 行为理解, 基础模型, 隐私保护