60GHz毫米波雷达CPD方案:Euro NCAP 2026实施指南

技术背景

Euro NCAP 2026 CPD强制要求

**儿童存在检测(CPD)**是Euro NCAP 2026新增强制要求:

检测对象 检测时限 警告方式 得分
婴儿(<1岁) 锁车后≤30s 车内蜂鸣+手机推送 5分
儿童(1-12岁) 锁车后≤60s 车内蜂鸣+手机推送 3分
宠物 锁车后≤90s 手机推送 1分

技术路线选择:

技术 穿透性 隐私性 成本 Euro NCAP推荐
60GHz雷达 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
79GHz雷达 ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐
超声波 ⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐
摄像头 ⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐
压力传感器 ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐

60GHz雷达优势

  1. 穿透性强:可穿透厚毯子、衣物检测生命体征
  2. 隐私友好:不涉及图像采集,符合GDPR要求
  3. 全天候工作:不受光照、温度影响
  4. 生命体征检测:呼吸、心跳信号提取

前沿研究:Chuhang Tech 60GHz雷达CE认证

新闻信息

  • 公司: Chuhang Tech(初杭科技)
  • 产品: 60GHz生命探测雷达全系
  • 认证: EU CE认证,符合Euro NCAP CPD直接感知要求
  • 时间: 2026年7月(1周前)

技术指标

指标 数值
工作频率 60GHz
分辨率 <5cm
穿透厚度 ≥10cm(毯子/衣物)
生命体征检测 呼吸(10-30次/分)、心跳(60-120次/分)
功耗 <2W
检测距离 0.5-3m

60GHz雷达CPD实现

1. 系统架构

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
250
251
252
253
import numpy as np

class CPDRadarSystem60GHz:
"""
60GHz毫米波雷达CPD系统
"""

def __init__(self):
# 雷达配置
self.radar_config = {
'frequency': 60e9, # 60GHz
'bandwidth': 4e9, # 4GHz带宽
'chirps_per_frame': 128,
'samples_per_chirp': 256,
'frame_rate': 20 # fps
}

# 生命体征阈值
self.vital_signs_thresholds = {
'breathing_rate': (10, 40), # 儿童/婴儿范围
'heart_rate': (60, 140),
'movement_amplitude': 0.01 # 最小运动幅度(米)
}

# 检测状态
self.detection_state = {
'detected': False,
'location': None,
'vital_signs': None,
'confidence': 0.0
}

def acquire_radar_data(self):
"""
获取雷达数据(模拟)

Returns:
radar_data: (n_chirps, n_samples, n_rx) 复数雷达数据
"""
# 实际实现需调用雷达硬件API
# 这里模拟返回数据
n_chirps = self.radar_config['chirps_per_frame']
n_samples = self.radar_config['samples_per_chirp']
n_rx = 4 # 4接收天线

# 模拟雷达数据(包含生命体征信号)
radar_data = np.random.randn(n_chirps, n_samples, n_rx) + \
1j * np.random.randn(n_chirps, n_samples, n_rx)

return radar_data

def process_radar_frame(self, radar_data):
"""
处理单帧雷达数据

Steps:
1. 距离-多普勒FFT
2. 目标检测
3. 生命体征提取

Returns:
detections: 检测结果列表
"""
# 1. 距离FFT(沿samples维度)
range_fft = np.fft.fft(radar_data, axis=1)

# 2. 多普勒FFT(沿chirps维度)
doppler_fft = np.fft.fft(range_fft, axis=0)

# 3. 目标检测(CFAR)
detections = self.cfar_detection(doppler_fft)

# 4. 生命体征提取
for det in detections:
vital_signs = self.extract_vital_signs(radar_data, det)
det['vital_signs'] = vital_signs

return detections

def cfar_detection(self, doppler_fft):
"""
CFAR目标检测
"""
# 简化实现:检测能量峰值
energy = np.abs(doppler_fft) ** 2
energy_mean = np.mean(energy, axis=(0, 1), keepdims=True)

# 阈值检测
threshold = 10 * energy_mean # 10dB
peaks = energy > threshold

# 提取检测点
detections = []
indices = np.where(peaks)

for i in range(min(len(indices[0]), 10)): # 最多10个目标
detection = {
'range_idx': indices[1][i],
'doppler_idx': indices[0][i],
'snr': energy[indices[0][i], indices[1][i]] / energy_mean[0, 0]
}
detections.append(detection)

return detections

def extract_vital_signs(self, radar_data, detection):
"""
提取生命体征

Args:
radar_data: 原始雷达数据
detection: 检测点信息

Returns:
vital_signs: {'breathing': float, 'heart_rate': float}
"""
# 提取相位信号(呼吸和心跳体现在相位变化)
range_idx = detection['range_idx']

# 沿chirp维度提取相位
phase_signal = np.angle(radar_data[:, range_idx, 0])

# 解相位
unwrapped_phase = np.unwrap(phase_signal)

# FFT分析生命体征频率
n_chirps = len(unwrapped_phase)
frame_duration = n_chirps / self.radar_config['frame_rate']

# FFT
fft_result = np.fft.fft(unwrapped_phase)
freqs = np.fft.fftfreq(n_chirps, d=frame_duration / n_chirps)

# 呼吸频段(0.1-0.5 Hz)
breathing_band = (0.1, 0.5)
breathing_idx = np.where((freqs >= breathing_band[0]) & (freqs <= breathing_band[1]))
breathing_power = np.max(np.abs(fft_result[breathing_idx]))

# 心跳频段(1.0-2.5 Hz)
heart_band = (1.0, 2.5)
heart_idx = np.where((freqs >= heart_band[0]) & (freqs <= heart_band[1]))
heart_power = np.max(np.abs(fft_result[heart_idx]))

# 估计频率
breathing_rate = freqs[breathing_idx][np.argmax(np.abs(fft_result[breathing_idx]))] * 60 # 次/分
heart_rate = freqs[heart_idx][np.argmax(np.abs(fft_result[heart_idx]))] * 60 # 次/分

return {
'breathing': abs(breathing_rate),
'heart_rate': abs(heart_rate),
'breathing_power': breathing_power,
'heart_power': heart_power
}

def classify_target(self, vital_signs):
"""
分类目标(婴儿/儿童/成人/宠物/物体)

Args:
vital_signs: 生命体征数据

Returns:
classification: {
'type': 'infant' | 'child' | 'adult' | 'pet' | 'object',
'confidence': float
}
"""
breathing = vital_signs['breathing']
heart_rate = vital_signs['heart_rate']

# 物体:无生命体征
if vital_signs['breathing_power'] < 0.1:
return {'type': 'object', 'confidence': 0.9}

# 婴儿:呼吸40-60次/分,心跳100-160次/分
if 30 <= breathing <= 60 and 100 <= heart_rate <= 160:
return {'type': 'infant', 'confidence': 0.85}

# 儿童:呼吸20-30次/分,心跳80-120次/分
if 15 <= breathing <= 35 and 70 <= heart_rate <= 130:
return {'type': 'child', 'confidence': 0.8}

# 成人:呼吸12-20次/分,心跳60-100次/分
if 10 <= breathing <= 25 and 60 <= heart_rate <= 100:
return {'type': 'adult', 'confidence': 0.75}

# 宠物:呼吸20-40次/分,心跳80-140次/分
if 15 <= breathing <= 45 and 80 <= heart_rate <= 150:
return {'type': 'pet', 'confidence': 0.7}

return {'type': 'unknown', 'confidence': 0.5}

def run_detection_cycle(self):
"""
运行检测周期

Returns:
result: 检测结果
"""
# 1. 获取雷达数据
radar_data = self.acquire_radar_data()

# 2. 处理帧
detections = self.process_radar_frame(radar_data)

# 3. 分类目标
results = []
for det in detections:
classification = self.classify_target(det['vital_signs'])

if classification['type'] in ['infant', 'child', 'pet']:
results.append({
'type': classification['type'],
'confidence': classification['confidence'],
'vital_signs': det['vital_signs'],
'location': self.range_idx_to_location(det['range_idx'])
})

return results

def range_idx_to_location(self, range_idx):
"""
将距离索引转换为物理位置
"""
# 简化:假设均匀分布
max_range = 3.0 # 米
n_samples = self.radar_config['samples_per_chirp']

location = range_idx / n_samples * max_range

if location < 1.0:
return 'front_seat'
elif location < 2.0:
return 'rear_left'
elif location < 3.0:
return 'rear_right'
else:
return 'trunk'


# 实际使用
if __name__ == "__main__":
cpd_system = CPDRadarSystem60GHz()

# 运行检测
results = cpd_system.run_detection_cycle()

print(f"检测到 {len(results)} 个目标")
for i, result in enumerate(results):
print(f"目标{i+1}: {result['type']} (置信度: {result['confidence']:.2f})")
print(f" 位置: {result['location']}")
print(f" 呼吸: {result['vital_signs']['breathing']:.1f} 次/分")
print(f" 心跳: {result['vital_signs']['heart_rate']:.1f} 次/分")

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
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
class MultiRadarCPD:
"""
多雷达融合CPD方案

配置:前座1个+后座2个(左/右)
"""

def __init__(self):
# 雷达配置
self.radars = {
'front': CPDRadarSystem60GHz(),
'rear_left': CPDRadarSystem60GHz(),
'rear_right': CPDRadarSystem60GHz()
}

# 融合参数
self.fusion_weights = {
'front': 0.4,
'rear_left': 0.3,
'rear_right': 0.3
}

def run_fusion_detection(self):
"""
多雷达融合检测
"""
all_detections = []

# 1. 各雷达独立检测
for radar_name, radar in self.radars.items():
detections = radar.run_detection_cycle()

for det in detections:
det['radar_source'] = radar_name
det['weight'] = self.fusion_weights[radar_name]

all_detections.extend(detections)

# 2. 位置融合(避免重复检测)
fused_detections = self.fuse_by_location(all_detections)

return fused_detections

def fuse_by_location(self, detections):
"""
按位置融合检测结果
"""
# 按位置分组
location_groups = {}

for det in detections:
loc = det['location']
if loc not in location_groups:
location_groups[loc] = []
location_groups[loc].append(det)

# 融合
fused = []

for location, dets in location_groups.items():
if len(dets) == 1:
fused.append(dets[0])
else:
# 多雷达检测同一位置:加权平均
confidence = np.mean([d['confidence'] * d['weight'] for d in dets])
breathing = np.mean([d['vital_signs']['breathing'] for d in dets])
heart_rate = np.mean([d['vital_signs']['heart_rate'] for d in dets])

fused.append({
'type': dets[0]['type'],
'confidence': confidence,
'location': location,
'vital_signs': {
'breathing': breathing,
'heart_rate': heart_rate
},
'radar_source': 'multi'
})

return fused

3. 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
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
class EuroNCAPCPDTest:
"""
Euro NCAP CPD测试场景
"""

def __init__(self):
self.cpd_system = MultiRadarCPD()

# Euro NCAP测试场景
self.test_scenarios = [
{
'id': 'CPD-01',
'description': '婴儿在后排座椅,覆盖厚毯子',
'target': 'infant',
'covering': 'thick_blanket',
'expected_result': 'detected',
'time_limit': 30 # 秒
},
{
'id': 'CPD-02',
'description': '儿童在后排座椅,正常坐姿',
'target': 'child',
'covering': 'none',
'expected_result': 'detected',
'time_limit': 60
},
{
'id': 'CPD-03',
'description': '儿童座椅(无儿童)',
'target': 'object',
'covering': 'none',
'expected_result': 'not_detected',
'time_limit': 120
},
{
'id': 'CPD-04',
'description': '宠物(小型犬)在后排',
'target': 'pet',
'covering': 'none',
'expected_result': 'detected',
'time_limit': 90
},
{
'id': 'CPD-05',
'description': '极端温度(-10°C)',
'target': 'child',
'covering': 'thin_blanket',
'expected_result': 'detected',
'time_limit': 60
}
]

def run_test(self, scenario_id):
"""
运行指定测试场景
"""
scenario = next(s for s in self.test_scenarios if s['id'] == scenario_id)

print(f"运行测试场景: {scenario['id']}")
print(f"描述: {scenario['description']}")

# 模拟测试环境
self.setup_environment(scenario)

# 运行检测
start_time = time.time()

while True:
detections = self.cpd_system.run_fusion_detection()

# 检查是否检测到目标
detected = len(detections) > 0

elapsed = time.time() - start_time

if detected:
print(f"✅ 检测成功,耗时: {elapsed:.1f}秒")
return {
'scenario_id': scenario_id,
'passed': True,
'detection_time': elapsed,
'detections': detections
}

if elapsed > scenario['time_limit']:
print(f"❌ 检测超时(>{scenario['time_limit']}秒)")
return {
'scenario_id': scenario_id,
'passed': False,
'detection_time': elapsed
}

time.sleep(1) # 每秒检测一次

def setup_environment(self, scenario):
"""
设置测试环境
"""
# 实际实现需控制测试环境
pass

def run_all_tests(self):
"""
运行所有测试
"""
results = []

for scenario in self.test_scenarios:
result = self.run_test(scenario['id'])
results.append(result)

# 统计通过率
passed = sum(1 for r in results if r['passed'])
total = len(results)

print(f"\n测试结果: {passed}/{total} 通过")

return results


import time

# 实际测试
if __name__ == "__main__":
test_suite = EuroNCAPCPDTest()
results = test_suite.run_all_tests()

边缘部署方案

1. 芯片选型

芯片 NPU性能 功耗 成本 推荐度
TI IWR6843AOP 专用DSP <2W $30 ⭐⭐⭐⭐⭐
Infineon BGT60ATR24C 专用DSP <1.5W $25 ⭐⭐⭐⭐
Qualcomm QCS8255 26 TOPS <5W $50 ⭐⭐⭐

2. INT8量化实现

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
import torch
import torch.nn as nn

class RadarSignalProcessorINT8(nn.Module):
"""
INT8量化的雷达信号处理网络
"""

def __init__(self):
super().__init__()

# 1D卷积层(处理距离-多普勒图)
self.conv1 = nn.Conv1d(4, 32, kernel_size=3, padding=1)
self.conv2 = nn.Conv1d(32, 64, kernel_size=3, padding=1)
self.conv3 = nn.Conv1d(64, 128, kernel_size=3, padding=1)

# 全连接层
self.fc1 = nn.Linear(128 * 256, 256)
self.fc2 = nn.Linear(256, 5) # 5类:infant/child/adult/pet/object

# 激活函数
self.relu = nn.ReLU()

def forward(self, x):
"""
前向传播

Args:
x: (batch, 4, 256) 距离-多普勒图(4个RX通道)

Returns:
logits: (batch, 5) 分类结果
"""
x = self.relu(self.conv1(x))
x = self.relu(self.conv2(x))
x = self.relu(self.conv3(x))

x = x.view(x.size(0), -1)

x = self.relu(self.fc1(x))
x = self.fc2(x)

return x


def quantize_to_int8(model):
"""
量化模型到INT8
"""
model.eval()

# 动态量化
quantized_model = torch.quantization.quantize_dynamic(
model,
{nn.Conv1d, nn.Linear},
dtype=torch.qint8
)

return quantized_model


# 实际部署
if __name__ == "__main__":
# 原始模型
model_fp32 = RadarSignalProcessorINT8()

# INT8量化
model_int8 = quantize_to_int8(model_fp32)

# 性能对比
dummy_input = torch.randn(1, 4, 256)

import time

# FP32推理
start = time.time()
output_fp32 = model_fp32(dummy_input)
time_fp32 = time.time() - start

# INT8推理
start = time.time()
output_int8 = model_int8(dummy_input)
time_int8 = time.time() - start

print(f"FP32推理时间: {time_fp32*1000:.2f}ms")
print(f"INT8推理时间: {time_int8*1000:.2f}ms")
print(f"加速比: {time_fp32/time_int8:.2f}x")

3.功耗与性能预估

指标 数值
模型大小 <2MB
推理延迟 <100ms
功耗 <1.5W
检测距离 0.5-3m
穿透厚度 ≥10cm

开发优先级

任务 周期 Euro NCAP得分 优先级
单雷达基础检测 2周 3分 🔴 高
生命体征提取 2周 2分 🔴 高
多雷达融合 3周 3分 🟡 中
INT8量化部署 1周 1分 🟡 中
Euro NCAP测试验证 2周 - 🔴 高

总结

60GHz毫米波雷达是Euro NCAP 2026 CPD要求的最佳技术选择

  • 穿透性:≥10cm毯子/衣物
  • 隐私性:符合GDPR要求
  • 成本:$25-30/雷达
  • 功耗:<2W

实施路径:

  1. 阶段1:单雷达基础检测(2周)
  2. 阶段2:生命体征提取(2周)
  3. 阶段3:多雷达融合(3周)
  4. 阶段4:INT8量化部署(1周)
  5. 阶段5:Euro NCAP测试验证(2周)

参考:

  1. Chuhang Tech 60GHz雷达CE认证,2026年7月
  2. Euro NCAP 2026 Protocol - Child Presence Detection
  3. TI IWR6843AOP 60GHz mmWave Sensor Datasheet

60GHz毫米波雷达CPD方案:Euro NCAP 2026实施指南
https://dapalm.com/2026/07/18/2026-07-18-06-60GHz-Radar-CPD-Euro-NCAP-2026-Implementation/
作者
Mars
发布于
2026年7月18日
许可协议