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
| import numpy as np
class CapacitiveHoD: """ 电容式离手检测信号处理器 """ def __init__(self, num_channels: int = 4): self.num_channels = num_channels self.baseline = np.zeros(num_channels) self.touch_threshold = 50 self.grip_threshold = 100 self.debounce_count = np.zeros(num_channels, dtype=int) self.debounce_limit = 3 def calibrate(self, baseline_readings: np.ndarray): """基线校准(无手时)""" self.baseline = baseline_readings def classify(self, readings: np.ndarray) -> dict: """ 分类握持状态 Args: readings: [num_channels] 原始ADC读数 Returns: { 'hands_on': bool, 'grip_type': str, 'grip_strength': float, 'channels_active': list } """ delta = readings - self.baseline channels_active = [] for i in range(self.num_channels): if delta[i] > self.grip_threshold: channels_active.append(i) self.debounce_count[i] = min(self.debounce_count[i] + 1, self.debounce_limit) elif delta[i] > self.touch_threshold: channels_active.append(i) self.debounce_count[i] = min(self.debounce_count[i] + 1, self.debounce_limit) else: self.debounce_count[i] = max(self.debounce_count[i] - 1, 0) confirmed_active = [i for i in channels_active if self.debounce_count[i] >= self.debounce_limit] hands_on = len(confirmed_active) > 0 grip_type = self._classify_grip(confirmed_active) if len(confirmed_active) > 0: grip_strength = float(np.mean(delta[confirmed_active])) / 200.0 else: grip_strength = 0.0 return { 'hands_on': hands_on, 'grip_type': grip_type, 'grip_strength': min(grip_strength, 1.0), 'channels_active': confirmed_active, 'raw_delta': delta.tolist() } def _classify_grip(self, active_channels: list) -> str: """识别握持类型""" if len(active_channels) == 0: return 'none' elif len(active_channels) == 1: return 'single_hand' elif len(active_channels) == 2: if 0 in active_channels and 1 in active_channels: return 'left_hand' elif 2 in active_channels and 3 in active_channels: return 'right_hand' elif 0 in active_channels and 3 in active_channels: return 'cross_grip' else: return 'two_hand' else: return 'full_grip'
if __name__ == "__main__": hod = CapacitiveHoD(num_channels=4) hod.calibrate(np.array([100, 100, 100, 100], dtype=float)) result = hod.classify(np.array([102, 101, 98, 103])) print(f"无手: hands_on={result['hands_on']}, type={result['grip_type']}") result = hod.classify(np.array([180, 170, 105, 103])) print(f"左手: hands_on={result['hands_on']}, type={result['grip_type']}") result = hod.classify(np.array([175, 165, 180, 170])) print(f"双手: hands_on={result['hands_on']}, type={result['grip_type']}")
|