151 lines
5.0 KiB
Python
151 lines
5.0 KiB
Python
import ctypes
|
||
import numpy as np
|
||
import matplotlib.pyplot as plt
|
||
|
||
class FPMS_DEVICE_C(ctypes.Structure):
|
||
_fields_ = [
|
||
("mn", ctypes.c_uint8),
|
||
("sn", ctypes.c_char * 32),
|
||
("swVersion", ctypes.c_char * 32),
|
||
("rows", ctypes.c_uint16),
|
||
("cols", ctypes.c_uint16)
|
||
]
|
||
|
||
class SMiTSenseSensor:
|
||
def __init__(self, dll_path = r"D:\Trae_space\BodyBalanceEvaluation\backend\tests\SMiTSenseUsbWrapper.dll"):
|
||
self.dll = ctypes.WinDLL(dll_path)
|
||
|
||
# 定义函数接口
|
||
self.dll.fpms_usb_init_wrapper.argtypes = [ctypes.c_int]
|
||
self.dll.fpms_usb_init_wrapper.restype = ctypes.c_int
|
||
|
||
self.dll.fpms_usb_get_device_list_wrapper.argtypes = [ctypes.POINTER(FPMS_DEVICE_C), ctypes.POINTER(ctypes.c_int)]
|
||
self.dll.fpms_usb_get_device_list_wrapper.restype = ctypes.c_int
|
||
|
||
self.dll.fpms_usb_open_wrapper.argtypes = [FPMS_DEVICE_C, ctypes.POINTER(ctypes.c_void_p)]
|
||
self.dll.fpms_usb_open_wrapper.restype = ctypes.c_int
|
||
|
||
self.dll.fpms_usb_read_frame_wrapper.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_uint16)]
|
||
self.dll.fpms_usb_read_frame_wrapper.restype = ctypes.c_int
|
||
|
||
self.dll.fpms_usb_config_light_wrapper.argtypes = [ctypes.c_void_p, ctypes.c_uint8, ctypes.c_uint8, ctypes.c_uint8, ctypes.c_uint8]
|
||
self.dll.fpms_usb_config_light_wrapper.restype = ctypes.c_int
|
||
|
||
self.dll.fpms_usb_close_wrapper.argtypes = [ctypes.c_void_p]
|
||
self.dll.fpms_usb_close_wrapper.restype = ctypes.c_int
|
||
|
||
self.device_handle = ctypes.c_void_p()
|
||
self.device_info = None
|
||
|
||
def initialize(self):
|
||
# 参数0是debug标志,参考示例
|
||
return self.dll.fpms_usb_init_wrapper(0) == 0
|
||
|
||
def get_device_list(self, max_devices=10):
|
||
devices = (FPMS_DEVICE_C * max_devices)()
|
||
device_count = ctypes.c_int()
|
||
ret = self.dll.fpms_usb_get_device_list_wrapper(devices, ctypes.byref(device_count))
|
||
if ret != 0 or device_count.value == 0:
|
||
return []
|
||
return devices[:device_count.value]
|
||
|
||
def open_device(self, device: FPMS_DEVICE_C):
|
||
handle = ctypes.c_void_p()
|
||
ret = self.dll.fpms_usb_open_wrapper(device, ctypes.byref(handle))
|
||
if ret == 0:
|
||
self.device_handle = handle
|
||
self.device_info = device
|
||
return True
|
||
return False
|
||
|
||
def config_light(self, r=1, g=56, b=183, a=214):
|
||
if not self.device_handle:
|
||
return False
|
||
ret = self.dll.fpms_usb_config_light_wrapper(self.device_handle, r, g, b, a)
|
||
return ret == 0
|
||
|
||
def read_frame(self):
|
||
if not self.device_handle or not self.device_info:
|
||
return None
|
||
rows = self.device_info.rows
|
||
cols = self.device_info.cols
|
||
frame_buffer = (ctypes.c_uint16 * (rows * cols))()
|
||
ret = self.dll.fpms_usb_read_frame_wrapper(self.device_handle, frame_buffer)
|
||
if ret != 0:
|
||
return None
|
||
# 转成 numpy 二维数组方便处理
|
||
data = np.ctypeslib.as_array(frame_buffer)
|
||
return data.reshape((rows, cols))
|
||
|
||
def close_device(self):
|
||
if self.device_handle:
|
||
ret = self.dll.fpms_usb_close_wrapper(self.device_handle)
|
||
self.device_handle = None
|
||
self.device_info = None
|
||
return ret == 0
|
||
return True
|
||
|
||
def main():
|
||
sensor = SMiTSenseSensor()
|
||
|
||
if not sensor.initialize():
|
||
print("初始化失败")
|
||
return
|
||
|
||
devices = sensor.get_device_list(20)
|
||
if not devices:
|
||
print("未发现设备")
|
||
return
|
||
print(f"发现设备数量: {len(devices)}")
|
||
for idx, dev in enumerate(devices):
|
||
print(f"设备{idx}: mn={dev.mn}, sn={dev.sn.decode(errors='ignore').strip()}, swVersion={dev.swVersion.decode(errors='ignore').strip()}, rows={dev.rows}, cols={dev.cols}")
|
||
|
||
# 依次尝试打开设备
|
||
opened = False
|
||
for device in devices:
|
||
print(f"尝试打开设备 SN: {device.sn.decode(errors='ignore').strip()}")
|
||
if sensor.open_device(device):
|
||
print("打开成功")
|
||
opened = True
|
||
break
|
||
else:
|
||
print("打开失败")
|
||
|
||
if not opened:
|
||
print("所有设备打开失败")
|
||
return
|
||
|
||
# 配置灯光
|
||
if sensor.config_light():
|
||
print("配置灯光成功")
|
||
else:
|
||
print("配置灯光失败")
|
||
|
||
# 准备显示图像
|
||
plt.ion()
|
||
fig, ax = plt.subplots()
|
||
img = None
|
||
|
||
try:
|
||
while True:
|
||
frame = sensor.read_frame()
|
||
if frame is None:
|
||
print("读取数据失败")
|
||
break
|
||
|
||
if img is None:
|
||
img = ax.imshow(frame, cmap='coolwarm', vmin=0, vmax=1023)
|
||
plt.title("SMiTSense 足底压力分布")
|
||
plt.colorbar(img, ax=ax)
|
||
else:
|
||
img.set_data(frame)
|
||
plt.pause(0.05)
|
||
except KeyboardInterrupt:
|
||
print("用户中断,退出")
|
||
finally:
|
||
sensor.close_device()
|
||
print("设备已关闭")
|
||
|
||
if __name__ == "__main__":
|
||
main()
|