from dataclasses import dataclass, field from typing import List import numpy as np @dataclass class MicState: """麦克风状态""" is_initialized: bool = False is_running: bool = False is_recording: bool = False volume: int = 0 error_message: str = "" @dataclass class SpeakerState: """扬声器状态""" is_initialized: bool = False is_running: bool = False is_decoding: bool = False is_paused: bool = False volume: int = 0 @dataclass class CameraState: """相机状态""" is_initialized: bool = False is_opened: bool = False is_streaming: bool = False is_recording: bool = False width: int = 0 height: int = 0 fps: int = 0 @dataclass class CameraIntrinsics: """相机内参(与Protobuf CameraIntrinsics对齐)""" cx: float = 0.0 # 对应Protobuf tag=1 cy: float = 0.0 # 对应Protobuf tag=2 fx: float = 0.0 # 对应Protobuf tag=3 fy: float = 0.0 # 对应Protobuf tag=4 # 畸变系数:固定5个元素(k1, k2, p1, p2, k3),与Protobuf tag=5对齐 coeffs: List[float] = field(default_factory=lambda: [0.0]*5) @dataclass class FreedomState: """灵巧手自由度状态""" dof_id: int = 0 angle: int = 0 speed: int = 0 force: int = 0 position: int = 0 current: int = 0 temperature: int = 0 error: int = 0 error_message: List[str] = field(default_factory=list) @dataclass class DexHandState: """灵巧手整体状态""" is_initialized: bool = False hands: List[FreedomState] = field(default_factory=lambda: [FreedomState() for _ in range(6)]) @dataclass class FacialExpressionState: """面部表情状态""" # 眉毛 left_eyebrow_outside_y: float = 0.0 left_eyebrow_inside_y: float = 0.0 right_eyebrow_outside_y: float = 0.0 right_eyebrow_inside_y: float = 0.0 # 眼睑 left_eye_upper_lid_y: float = 0.0 left_eye_lower_lid_y: float = 0.0 right_eye_upper_lid_y: float = 0.0 right_eye_lower_lid_y: float = 0.0 # 眼球 left_eye_ball_x: float = 0.0 left_eye_ball_y: float = 0.0 right_eye_ball_x: float = 0.0 right_eye_ball_y: float = 0.0 # 鼻子 left_nose_y: float = 0.0 right_nose_y: float = 0.0 # 嘴巴 upper_lip_y: float = 0.0 upper_lip_z: float = 0.0 lower_lip_y: float = 0.0 lower_lip_z: float = 0.0 # 左唇角 upper_left_lip_x: float = 0.0 upper_left_lip_y: float = 0.0 left_corner_lip_x: float = 0.0 left_corner_lip_y: float = 0.0 lower_left_lip_x: float = 0.0 lower_left_lip_y: float = 0.0 # 右唇角 upper_right_lip_x: float = 0.0 upper_right_lip_y: float = 0.0 right_corner_lip_x: float = 0.0 right_corner_lip_y: float = 0.0 lower_right_lip_x: float = 0.0 lower_right_lip_y: float = 0.0 # 下巴 jaw_x: float = 0.0 jaw_y: float = 0.0 @dataclass class FingerTactileData: """手指触觉数据""" data: np.ndarray = None rows: int = 0 cols: int = 0 byteSize: int = 0 name: str = "" def __post_init__(self): if self.data is None and self.rows > 0 and self.cols > 0: self.data = np.zeros((self.rows, self.cols), dtype=np.uint16) @dataclass class PalmTactileData: """手掌触觉数据""" data: np.ndarray = None rows: int = 8 cols: int = 14 byteSize: int = 224 name: str = "掌心" def __post_init__(self): if self.data is None: self.data = np.zeros((self.rows, self.cols), dtype=np.uint16) @dataclass class HandTactileSensors: """整只手的触觉传感器数据""" pinky_tip: FingerTactileData = None pinky_finger: FingerTactileData = None pinky_pad: FingerTactileData = None ring_tip: FingerTactileData = None ring_finger: FingerTactileData = None ring_pad: FingerTactileData = None middle_tip: FingerTactileData = None middle_finger: FingerTactileData = None middle_pad: FingerTactileData = None index_tip: FingerTactileData = None index_finger: FingerTactileData = None index_pad: FingerTactileData = None thumb_tip: FingerTactileData = None thumb_finger: FingerTactileData = None thumb_middle: FingerTactileData = None thumb_pad: FingerTactileData = None palm: PalmTactileData = None def __post_init__(self): """初始化所有传感器数据""" # 小拇指 self.pinky_tip = FingerTactileData(rows=3, cols=3, byteSize=18, name="小拇指指端") self.pinky_finger = FingerTactileData(rows=12, cols=8, byteSize=192, name="小拇指指尖") self.pinky_pad = FingerTactileData(rows=10, cols=8, byteSize=160, name="小拇指指腹") # 无名指 self.ring_tip = FingerTactileData(rows=3, cols=3, byteSize=18, name="无名指指端") self.ring_finger = FingerTactileData(rows=12, cols=8, byteSize=192, name="无名指指尖") self.ring_pad = FingerTactileData(rows=10, cols=8, byteSize=160, name="无名指指腹") # 中指 self.middle_tip = FingerTactileData(rows=3, cols=3, byteSize=18, name="中指指端") self.middle_finger = FingerTactileData(rows=12, cols=8, byteSize=192, name="中指指尖") self.middle_pad = FingerTactileData(rows=10, cols=8, byteSize=160, name="中指指腹") # 食指 self.index_tip = FingerTactileData(rows=3, cols=3, byteSize=18, name="食指指端") self.index_finger = FingerTactileData(rows=12, cols=8, byteSize=192, name="食指指尖") self.index_pad = FingerTactileData(rows=10, cols=8, byteSize=160, name="食指指腹") # 大拇指 self.thumb_tip = FingerTactileData(rows=3, cols=3, byteSize=18, name="大拇指指端") self.thumb_finger = FingerTactileData(rows=12, cols=8, byteSize=192, name="大拇指尖") self.thumb_middle = FingerTactileData(rows=3, cols=3, byteSize=18, name="大拇指指中") self.thumb_pad = FingerTactileData(rows=12, cols=8, byteSize=192, name="大拇指指腹") # 掌心 self.palm = PalmTactileData() def get_finger_name(self, finger_type): """获取手指名称""" from .enums import FingerType names = { FingerType.PINKY: "小拇指", FingerType.RING: "无名指", FingerType.MIDDLE: "中指", FingerType.INDEX: "食指", FingerType.THUMB: "大拇指" } return names.get(finger_type, "未知") def print_summary(self): """打印传感器数据摘要信息""" print(f" 小拇指指端: {self.pinky_tip.rows}x{self.pinky_tip.cols} (数据大小: {self.pinky_tip.byteSize} bytes)") print(f" 无名指指端: {self.ring_tip.rows}x{self.ring_tip.cols} (数据大小: {self.ring_tip.byteSize} bytes)") print(f" 中指指端: {self.middle_tip.rows}x{self.middle_tip.cols} (数据大小: {self.middle_tip.byteSize} bytes)") print(f" 食指指端: {self.index_tip.rows}x{self.index_tip.cols} (数据大小: {self.index_tip.byteSize} bytes)") print(f" 大拇指指端: {self.thumb_tip.rows}x{self.thumb_tip.cols} (数据大小: {self.thumb_tip.byteSize} bytes)") print(f" 大拇指指中: {self.thumb_middle.rows}x{self.thumb_middle.cols} (数据大小: {self.thumb_middle.byteSize} bytes)") print(f" 掌心: {self.palm.rows}x{self.palm.cols} (数据大小: {self.palm.byteSize} bytes)") # 机器人相关数据结构 @dataclass class JointCmd: """关节控制命令""" joint_name: str = "" # 关节名称 rad: float = 0.0 # 弧度 vel: float = 0.0 # 角速度,rad/s @dataclass class Pose3D: """3D位姿""" x: float = 0.0 # X坐标 y: float = 0.0 # Y坐标 z: float = 0.0 # Z坐标 rx: float = 0.0 # 绕X轴旋转(弧度) ry: float = 0.0 # 绕Y轴旋转(弧度) rz: float = 0.0 # 绕Z轴旋转(弧度) def to_array(self) -> np.ndarray: """转换为numpy数组""" return np.array([self.x, self.y, self.z, self.rx, self.ry, self.rz]) @classmethod def from_array(cls, arr: np.ndarray) -> 'Pose3D': """从numpy数组创建Pose3D""" return cls(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]) @dataclass class JointState: """关节状态""" name: List[str] = field(default_factory=list) # 关节名称列表 position: List[float] = field(default_factory=list) # 关节位置列表(弧度) velocity: List[float] = field(default_factory=list) # 关节速度列表(rad/s) effort: List[float] = field(default_factory=list) # 关节力矩列表 timestamp: float = 0.0 # 时间戳 def __post_init__(self): """确保列表长度一致""" if len(self.name) > 0: n_joints = len(self.name) self.position = self.position[:n_joints] + [0.0] * (n_joints - len(self.position)) self.velocity = self.velocity[:n_joints] + [0.0] * (n_joints - len(self.velocity)) self.effort = self.effort[:n_joints] + [0.0] * (n_joints - len(self.effort)) def get_joint_by_name(self, joint_name: str) -> tuple: """根据关节名称获取状态""" if joint_name in self.name: idx = self.name.index(joint_name) return (self.position[idx], self.velocity[idx], self.effort[idx]) return (0.0, 0.0, 0.0) def to_dict(self) -> dict: """转换为字典格式""" return { 'name': self.name, 'positions': self.position, 'velocities': self.velocity, 'efforts': self.effort, 'timestamp': self.timestamp }