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
| import numpy as np from dataclasses import dataclass from typing import List, Tuple
@dataclass class HapticSensation: """触觉刺激参数定义""" name: str frequency_hz: float duration_ms: int intensity: float pattern: str class KnucklesNotificationSystem: """ 方向盘背手超声波触觉通知系统 论文: Frontiers in Computer Science, 2024 核心: 超声波相控阵 → 手背指关节 → 4种通知编码 评估: 20名驾驶员,94%识别率 关键发现: 1. 握方向盘时手背感知增强(声波反射) 2. 不受车辆振动遮蔽 3. 4种通知94%正确识别 4. 不影响驾驶任务(路径偏差无显著差异) """ NOTIFICATIONS = { 'incoming_call': HapticSensation( name='来电', frequency_hz=100, duration_ms=2000, intensity=0.7, pattern='continuous' ), 'text_message': HapticSensation( name='短信', frequency_hz=150, duration_ms=800, intensity=0.5, pattern='pulsed' ), 'navigation_alert': HapticSensation( name='导航', frequency_hz=80, duration_ms=1200, intensity=0.6, pattern='ramp_up' ), 'driver_warning': HapticSensation( name='驾驶警告', frequency_hz=200, duration_ms=500, intensity=0.9, pattern='rapid' ) } def __init__(self, transducer_count=256): """ Args: transducer_count: 超声换能器数量(典型256个) """ self.num_transducers = transducer_count self.array_frequency = 40000 self.focus_distance = 0.15 self.element_spacing = 0.005 def compute_phase_delays(self, target_point: Tuple[float, float, float]) -> np.ndarray: """ 计算相控阵延迟以聚焦到目标点 Args: target_point: (x, y, z) 目标坐标(米) Returns: phases: 每个阵元的相位延迟(弧度) """ c = 343.0 grid_size = int(np.sqrt(self.num_transducers)) x = np.linspace(-grid_size/2 * self.element_spacing, grid_size/2 * self.element_spacing, grid_size) y = np.linspace(-grid_size/2 * self.element_spacing, grid_size/2 * self.element_spacing, grid_size) xx, yy = np.meshgrid(x, y) distances = np.sqrt( (xx - target_point[0])**2 + (yy - target_point[1])**2 + target_point[2]**2 ) phases = 2 * np.pi * self.array_frequency * distances / c phases = phases % (2 * np.pi) return phases.flatten() def generate_amplitude_modulation(self, sensation: HapticSensation, duration_s: float = None) -> np.ndarray: """ 生成幅度调制信号 Args: sensation: 触觉参数 duration_s: 信号持续时间(秒) Returns: am_signal: 幅度调制后的信号 """ if duration_s is None: duration_s = sensation.duration_ms / 1000 fs = 44100 t = np.arange(int(fs * duration_s)) / fs carrier = np.sin(2 * np.pi * self.array_frequency * t) if sensation.pattern == 'continuous': modulation = sensation.intensity * np.ones_like(t) elif sensation.pattern == 'pulsed': modulation = np.zeros_like(t) pulse1_end = int(0.2 * fs) pulse2_start = int(0.3 * fs) pulse2_end = int(0.5 * fs) modulation[:pulse1_end] = sensation.intensity modulation[pulse2_start:pulse2_end] = sensation.intensity elif sensation.pattern == 'ramp_up': ramp = np.linspace(0, sensation.intensity, len(t)) modulation = ramp elif sensation.pattern == 'rapid': modulation = np.zeros_like(t) pulse_duration = int(0.05 * fs) gap = int(0.03 * fs) for i in range(5): start = i * (pulse_duration + gap) end = start + pulse_duration if end < len(modulation): modulation[start:end] = sensation.intensity else: modulation = sensation.intensity * np.ones_like(t) am_signal = carrier * modulation return am_signal def trigger_notification(self, notification_type: str) -> dict: """ 触发通知 Args: notification_type: 'incoming_call', 'text_message', 'navigation_alert', 'driver_warning' """ sensation = self.NOTIFICATIONS.get(notification_type) if not sensation: return {'error': f'unknown notification: {notification_type}'} target = (0.0, 0.05, 0.15) phases = self.compute_phase_delays(target) signal = self.generate_amplitude_modulation(sensation) return { 'notification': sensation.name, 'target': target, 'frequency_hz': sensation.frequency_hz, 'duration_ms': sensation.duration_ms, 'pattern': sensation.pattern, 'intensity': sensation.intensity, 'phases_count': len(phases), 'signal_samples': len(signal) }
if __name__ == "__main__": system = KnucklesNotificationSystem(transducer_count=256) print("=== Knuckles通知系统测试 ===\n") for ntype in ['incoming_call', 'text_message', 'navigation_alert', 'driver_warning']: result = system.trigger_notification(ntype) print(f"通知: {result['notification']}") print(f" 频率: {result['frequency_hz']}Hz") print(f" 时长: {result['duration_ms']}ms") print(f" 模式: {result['pattern']}") print(f" 强度: {result['intensity']}") print(f" 阵元数: {result['phases_count']}") print(f" 信号采样数: {result['signal_samples']}") print() print("=== 论文测试结果 ===") print(f"参与者: 20名驾驶员") print(f"通知识别率: 94%") print(f"路径偏差: 无显著影响(p>0.05)") print(f"振动遮蔽: 无影响(成功率不降)") print() print("关键发现:") print("1. 握方向盘时手背感知增强(声波反射聚焦)") print("2. 不受车辆振动遮蔽(vs 方向盘内嵌振动电机)") print("3. 4种通知可区分(94%准确率)") print("4. 支持hands-on-the-wheel范式(不松手)")
|