UWB雷达CPD儿童检测:零BOM成本的生命体征监测方案


Euro NCAP CPD强制要求

2025年起CPD成为五星评级必须项

要求 说明 检测范围
检测对象 所有乘员,特别是儿童 新生儿到6岁
检测信号 呼吸、心跳、微动 呼吸率 18-30 BPM
检测区域 整个座舱 所有座位+脚部空间
误报率 ≤5% 避免频繁误警
漏检率 ≤1% 零容忍

热车死亡统计数据

  • 美国自1990年以来已有1050名儿童死于车内中暑
  • 2023年美国通过Hot Cars Act强制要求CPD
  • Euro NCAP 2025要求所有新车配备CPD

UWB雷达技术原理

什么是UWB雷达?

UWB(Ultra-Wideband)超宽带雷达

使用纳秒级脉冲信号,带宽 >500MHz,实现厘米级距离分辨率

1
2
3
4
5
6
7
8
9
10
11
12
13
# UWB雷达参数示例
uwb_params = {
"bandwidth": "500 MHz - 7.5 GHz", # 带宽范围
"pulse_width": "1-2 ns", # 脉冲宽度(纳秒)
"range_resolution": "< 2 cm", # 距离分辨率
"power_consumption": "< 100 µW", # 功耗(待机模式)
"penetration": "非导电材料穿透", # 材料穿透能力
"privacy": "无图像采集", # 隐私保护
}

print("UWB雷达核心参数:")
for key, value in uwb_params.items():
print(f" {key}: {value}")

UWB vs 60GHz雷达对比

指标 UWB雷达 60GHz毫米波雷达
带宽 500MHz-7.5GHz 7GHz (57-64GHz)
距离分辨率 <2cm ~2cm
功耗 <100µW(待机) ~10mW(待机)
材料穿透 优秀 一般
隐私保护 原生支持 原生支持
成本 零增量BOM 需新增硬件
集成难度 低(复用数字钥匙) 中等

NOVELDA X7 UWB解决方案

核心特性

X7 UWB雷达系统级芯片

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
class NOVELDA_X7_UWB:
"""NOVELDA X7 UWB CPD & Vital Signs传感器"""

def __init__(self):
self.chip_name = "X7 UWB Radar SoC"
self.detection_modes = [
"child_presence_detection",
"vital_signs_monitoring",
"seat_occupancy",
"intrusion_detection"
]

def get_specs(self):
"""获取技术规格"""
return {
"range_resolution": "< 2 cm", # 距离分辨率
"detection_sensitivity": "breath + heartbeat", # 检测灵敏度
"power_idle": "< 100 µW", # 待机功耗
"coverage": "whole cabin", # 覆盖范围
"integration": "behind material", # 集成方式
"response_time": "< 30 seconds", # 响应时间
}

def detect_child(self, cabin_zone: str):
"""儿童检测主流程"""
# 1. 扫描指定区域
range_doppler = self.scan_zone(cabin_zone)

# 2. 提取微动信号
micromotion = self.extract_micromotion(range_doppler)

# 3. 生命体征分析
vitals = self.analyze_vitals(micromotion)

# 4. 判断是否存在儿童
if vitals["breathing_rate"] > 0:
return {
"detected": True,
"breathing_rate": vitals["breathing_rate"],
"heartbeat": vitals["heartbeat"],
"position": cabin_zone
}
return {"detected": False}


# 实例化测试
sensor = NOVELDA_X7_UWB()
specs = sensor.get_specs()

print("NOVELDA X7 UWB规格:")
print(f" 距离分辨率:{specs['range_resolution']}")
print(f" 待机功耗:{specs['power_idle']}")
print(f" 覆盖范围:{specs['coverage']}")
print(f" 响应时间:{specs['response_time']}")

检测流程

graph TD
    A[车辆熄火锁门] --> B[UWB传感器启动扫描]
    B --> C{检测到微动信号?}
    C -->|否| D[继续待机监测]
    D --> B
    C -->|是| E[分析生命体征]
    E --> F{判断为儿童?}
    F -->|是| G[触发报警]
    F -->|否| H[过滤误报]
    G --> I[推送手机APP]
    G --> J[车鸣笛+灯光]
    G --> K[呼叫紧急服务]

Range-Doppler数据处理

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
import numpy as np
from scipy import signal
from scipy.fft import fft, fftshift

class UWBSignalProcessor:
"""UWB雷达信号处理器"""

def __init__(self,
sample_rate: int = 100,
range_bins: int = 256,
doppler_bins: int = 64):
self.sample_rate = sample_rate
self.range_bins = range_bins
self.doppler_bins = doppler_bins

def generate_range_doppler(self, raw_data: np.ndarray):
"""
生成Range-Doppler图

Args:
raw_data: 原始UWB数据,shape=(slow_time, fast_time)

Returns:
range_doppler: Range-Doppler图,shape=(doppler_bins, range_bins)
"""
# 快时间FFT(距离)
range_fft = fft(raw_data, n=self.range_bins, axis=1)

# 慢时间FFT(多普勒)
range_doppler = fft(range_fft, n=self.doppler_bins, axis=0)
range_doppler = fftshift(range_doppler, axes=0)

# 取幅度
range_doppler_db = 20 * np.log10(np.abs(range_doppler) + 1e-10)

return range_doppler_db

def extract_breathing_signal(self,
range_doppler: np.ndarray,
target_range_bin: int):
"""
从Range-Doppler图中提取呼吸信号

Args:
range_doppler: Range-Doppler图
target_range_bin: 目标距离bin(对应乘员胸部)

Returns:
breathing_signal: 呼吸信号序列
"""
# 提取低频多普勒(对应呼吸运动)
low_doppler_bins = range_doppler[
self.doppler_bins//2-5 : self.doppler_bins//2+5,
target_range_bin
]

# 平均得到呼吸信号
breathing_signal = np.mean(low_doppler_bins, axis=0)

return breathing_signal

def estimate_breathing_rate(self, breathing_signal: np.ndarray):
"""
估计呼吸频率

Args:
breathing_signal: 呼吸信号序列

Returns:
bpm: 每分钟呼吸次数
"""
# 带通滤波(0.2-0.8 Hz,对应12-48 BPM)
sos = signal.butter(4, [0.2, 0.8], btype='band',
fs=self.sample_rate, output='sos')
filtered = signal.sosfilt(sos, breathing_signal)

# FFT频谱分析
freq = np.fft.rfftfreq(len(filtered), 1/self.sample_rate)
spectrum = np.abs(np.fft.rfft(filtered))

# 找主频率
peak_idx = np.argmax(spectrum)
peak_freq = freq[peak_idx]

# 转换为BPM
bpm = peak_freq * 60

return bpm


# 实际测试
if __name__ == "__main__":
processor = UWBSignalProcessor()

# 模拟数据(60秒采集)
raw_data = np.random.randn(6000, 256) * 0.1 # 添加微弱呼吸信号
t = np.linspace(0, 60, 6000)
breathing_pattern = np.sin(2 * np.pi * 0.35 * t)[:, np.newaxis] # 21 BPM
raw_data[:, 128] += breathing_pattern * 10 # 模拟呼吸

# 处理
range_doppler = processor.generate_range_doppler(raw_data)
breathing_signal = processor.extract_breathing_signal(range_doppler, 128)
bpm = processor.estimate_breathing_rate(breathing_signal)

print(f"检测到呼吸频率:{bpm:.1f} BPM")
print(f"新生儿正常范围:18-30 BPM")
print(f"检测结果:{'正常' if 18 <= bpm <= 30 else '异常'}")

Ceva UWB零BOM成本方案

核心创新:复用数字钥匙硬件

传统方案 vs Ceva方案

方案 硬件需求 BOM成本 集成复杂度
传统CPD 新增60GHz雷达 +$20-50
Ceva UWB 复用数字钥匙UWB $0
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
class CevaUWBDualUse:
"""
Ceva UWB双用途方案
同一硬件支持数字钥匙 + CPD
"""

def __init__(self):
self.modes = {
"digital_key": {
"standard": "CCC Digital Key 4.0",
"function": "安全测距、被动进入",
"accuracy": "厘米级ToF/AoA",
},
"cpd": {
"standard": "Euro NCAP CPD",
"function": "儿童检测、生命体征",
"sensitivity": "<1 BPM",
}
}

def switch_mode(self, mode: str):
"""切换工作模式"""
if mode == "digital_key":
# 数字钥匙模式
return self.configure_digital_key()
elif mode == "cpd":
# CPD模式
return self.configure_cpd()
else:
raise ValueError(f"未知模式: {mode}")

def configure_digital_key(self):
"""配置数字钥匙模式"""
return {
"rx_antennas": 3, # 3天线AoA
"tx_power": -14, # dBm/MHz
"ranging_interval": 100, # ms
"security": "IEEE 802.15.4z STS",
}

def configure_cpd(self):
"""配置CPD模式"""
return {
"rx_antennas": 1, # 单天线足够
"tx_power": -20, # 低功率
"scan_interval": 1000, # ms
"detection_sensitivity": "breath + heartbeat",
}


# 测试
dual_use = CevaUWBDualUse()
print("双用途模式:")
for mode, info in dual_use.modes.items():
print(f" {mode}: {info['function']}")

信号处理流水线

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
class UWBRadarPipeline:
"""UWB雷达信号处理流水线"""

def __init__(self):
self.pipeline_stages = [
"data_extraction",
"spatial_gating",
"rbm_detection",
"source_separation",
"vital_signs_estimation"
]

def process(self, cir_data: np.ndarray):
"""
完整处理流水线

Args:
cir_data: Channel Impulse Response数据

Returns:
result: 生命体征检测结果
"""
# 阶段1: 数据提取
raw_signal = self.extract_raw_signal(cir_data)

# 阶段2: 空间门控
gated_signal = self.spatial_gating(raw_signal)

# 阶段3: 快速身体运动检测
clean_signal, rbm_events = self.detect_rbm(gated_signal)

# 阶段4: 源分离
breathing, heartbeat = self.source_separation(clean_signal)

# 阶段5: 生命体征估计
result = self.estimate_vitals(breathing, heartbeat)

return result

def extract_raw_signal(self, cir_data):
"""提取原始信号"""
# 提取主反射峰(对应乘员胸部)
peak_idx = np.argmax(np.abs(cir_data), axis=1)
return cir_data[np.arange(len(cir_data)), peak_idx]

def spatial_gating(self, signal):
"""空间门控,滤除静态杂波"""
# 高通滤波
sos = signal.butter(4, 0.1, btype='high',
fs=100, output='sos')
return signal.sosfilt(sos, signal)

def detect_rbm(self, signal):
"""检测快速身体运动(RBM)"""
window_size = 100
threshold = 3.0 # 标准差阈值

# 滑动窗口方差
variances = []
for i in range(0, len(signal) - window_size, window_size//2):
window = signal[i:i+window_size]
variances.append(np.std(window))

variances = np.array(variances)

# 标记RBM事件
rbm_mask = variances > threshold * np.median(variances)

# 过滤RBM段
clean_signal = signal.copy()
rbm_indices = np.where(rbm_mask)[0] * (window_size // 2)
clean_signal[rbm_indices] = 0

return clean_signal, rbm_mask

def source_separation(self, signal):
"""分离呼吸和心跳信号"""
# 呼吸: 0.2-0.8 Hz (12-48 BPM)
sos_breath = signal.butter(4, [0.2, 0.8], btype='band',
fs=100, output='sos')
breathing = signal.sosfilt(sos_breath, signal)

# 心跳: 1.0-2.0 Hz (60-120 BPM)
sos_heart = signal.butter(4, [1.0, 2.0], btype='band',
fs=100, output='sos')
heartbeat = signal.sosfilt(sos_heart, signal)

return breathing, heartbeat

def estimate_vitals(self, breathing, heartbeat):
"""估计生命体征"""
# 呼吸率
freq_breath = np.fft.rfftfreq(len(breathing), 0.01)
spectrum_breath = np.abs(np.fft.rfft(breathing))
breath_freq = freq_breath[np.argmax(spectrum_breath)]
breath_bpm = breath_freq * 60

# 心率
freq_heart = np.fft.rfftfreq(len(heartbeat), 0.01)
spectrum_heart = np.abs(np.fft.rfft(heartbeat))
heart_freq = freq_heart[np.argmax(spectrum_heart)]
heart_bpm = heart_freq * 60

return {
"breathing_rate": breath_bpm,
"heart_rate": heart_bpm,
"confidence": np.max(spectrum_breath) / np.sum(spectrum_breath)
}


# 测试
if __name__ == "__main__":
pipeline = UWBRadarPipeline()

# 模拟CIR数据
t = np.linspace(0, 60, 6000)
breathing = np.sin(2 * np.pi * 0.35 * t) # 21 BPM
heartbeat = np.sin(2 * np.pi * 1.5 * t) # 90 BPM
noise = np.random.randn(6000) * 0.1

cir_data = np.random.randn(6000, 256) * 0.1
cir_data[:, 128] += (breathing + heartbeat * 0.3 + noise) * 10

# 处理
result = pipeline.process(cir_data)
print("生命体征检测结果:")
print(f" 呼吸率: {result['breathing_rate']:.1f} BPM")
print(f" 心率: {result['heart_rate']:.1f} BPM")
print(f" 置信度: {result['confidence']:.2f}")

Euro NCAP CPD测试场景

测试场景清单

场景编号 测试对象 位置 姿态 通过条件
CPD-01 新生儿模型 后排座椅 正常坐姿 ≤30s检测到
CPD-02 新生儿模型 后排地板 躺卧 ≤60s检测到
CPD-03 1岁儿童模型 安全座椅 正常 ≤30s检测到
CPD-04 3岁儿童模型 后排座椅 睡眠 ≤30s检测到
CPD-05 6岁儿童模型 后排座椅 蜷缩 ≤30s检测到
CPD-06 宠物(狗) 后排座椅 - ≤60s检测到

新生儿呼吸率检测

Euro NCAP要求

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
# Euro NCAP新生儿呼吸率检测标准
newborn_breathing = {
"normal_range": (18, 30), # BPM
"detection_time": 30, # 秒
"accuracy": "> 95%", # 检测准确率
"false_positive": "< 5%", # 误报率
}

def check_breathing_rate(bpm: float) -> str:
"""检查呼吸率是否在正常范围"""
min_bpm, max_bpm = newborn_breathing["normal_range"]

if min_bpm <= bpm <= max_bpm:
return f"✅ 正常 ({bpm:.1f} BPM)"
elif bpm < min_bpm:
return f"⚠️ 呼吸过缓 ({bpm:.1f} BPM)"
else:
return f"⚠️ 呼吸过速 ({bpm:.1f} BPM)"


# 测试
test_cases = [15, 20, 24, 28, 35]
print("新生儿呼吸率检测测试:")
for bpm in test_cases:
print(f" {bpm} BPM: {check_breathing_rate(bpm)}")

IMS开发落地启示

1. 硬件选型策略

车型定位 推荐方案 成本 理由
入门级 UWB复用方案 $0 零增量成本
中端 UWB + 单摄像头 +$20 增强鲁棒性
高端 UWB + 60GHz + 摄像头融合 +$50 多重冗余

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
# UWB传感器安装位置
installation_options = [
{
"position": "顶棚中央",
"coverage": "全舱",
"pros": "最佳覆盖、安装简单",
"cons": "需隐藏在材料后",
},
{
"position": "B柱内侧",
"coverage": "后排座位",
"pros": "靠近儿童安全座椅",
"cons": "覆盖角度受限",
},
{
"position": "中控台上方",
"coverage": "前排+部分后排",
"pros": "兼顾DMS功能",
"cons": "后排检测减弱",
},
]

# 推荐:顶棚中央(覆盖全舱)
recommended = installation_options[0]
print(f"推荐安装位置:{recommended['position']}")
print(f"覆盖范围:{recommended['coverage']}")

3. 算法优化方向

优化方向 方法 预期效果
噪声抑制 自适应杂波对消 信噪比 +10dB
RBM鲁棒性 多窗口方差检测 减少90%误报
多乘员分离 空间聚类+源分离 准确分离3人
低功耗 间歇扫描策略 待机功耗 <50µW

4. 与Euro NCAP对接

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
class EuroNCAP_CPD_Compliance:
"""Euro NCAP CPD合规检查"""

def __init__(self):
self.requirements = {
"detection_time": 30, # 秒
"breathing_accuracy": 95, # %
"false_positive": 5, # %
"coverage": "whole_cabin",
}

def validate(self, test_results: dict) -> dict:
"""验证合规性"""
passed = []
failed = []

# 检测时间
if test_results["detection_time"] <= self.requirements["detection_time"]:
passed.append("detection_time")
else:
failed.append("detection_time")

# 呼吸检测准确率
if test_results["breathing_accuracy"] >= self.requirements["breathing_accuracy"]:
passed.append("breathing_accuracy")
else:
failed.append("breathing_accuracy")

# 误报率
if test_results["false_positive"] <= self.requirements["false_positive"]:
passed.append("false_positive")
else:
failed.append("false_positive")

return {
"compliant": len(failed) == 0,
"passed": passed,
"failed": failed,
}


# 测试
compliance = EuroNCAP_CPD_Compliance()
test_results = {
"detection_time": 25,
"breathing_accuracy": 97,
"false_positive": 3,
}

result = compliance.validate(test_results)
print(f"Euro NCAP合规: {'✅ 通过' if result['compliant'] else '❌ 不通过'}")
print(f"通过项: {result['passed']}")
print(f"失败项: {result['failed']}")

5. 开发优先级

优先级 功能模块 时间估算 依赖
P0 UWB硬件集成 1-2月 数字钥匙团队
P0 基础呼吸检测算法 1月 信号处理团队
P1 RBM鲁棒性优化 2月 测试数据
P1 多乘员分离 2月 标注数据
P2 与DMS/OMS融合 3月 整体架构

总结

UWB雷达CPD方案的核心优势

  1. 零增量BOM成本:复用数字钥匙UWB硬件
  2. 低功耗:待机 <100µW,支持Always-on
  3. 隐私友好:无图像采集,符合GDPR
  4. 高灵敏度:检测呼吸/心跳微动
  5. 材料穿透:可隐藏安装,不影响内饰

对IMS开发的启示

  • 优先选择UWB复用方案,降低成本
  • 算法重点:噪声抑制 + RBM鲁棒性 + 多乘员分离
  • 与Euro NCAP对接:确保30秒检测时间 + 95%准确率

参考文献

  1. NOVELDA X7 UWB CPD & Vital Signs Sensor: https://novelda.com/ultra-wideband-child-presence-sensor/
  2. Ceva UWB Radar White Paper 2026: https://www.ceva-ip.com/resourcecenter/uwb-radar-white-paper/
  3. Euro NCAP CPD Test Protocol v1.3: https://www.euroncap.com/
  4. CCC Digital Key Release 4.0 Specification
  5. IEEE 802.15.4z / 802.15.4ab Standard

UWB雷达CPD儿童检测:零BOM成本的生命体征监测方案
https://dapalm.com/2026/06/21/2026-06-21-uwb-cpd-vital-signs-monitoring/
作者
Mars
发布于
2026年6月21日
许可协议