add stream raw frame access

This commit is contained in:
lenn
2026-05-26 22:22:28 +08:00
parent 705375085f
commit 47722bb383
13 changed files with 358 additions and 85 deletions

View File

@@ -1,3 +1,4 @@
#include <algorithm>
#include <chrono>
#include <condition_variable>
#include <cstdint>
@@ -7,6 +8,7 @@
#include <queue>
#include <string>
#include <thread>
#include <vector>
#include "../../include/eskin_ffi.h"
@@ -64,20 +66,34 @@ static void demo_streaming(EskinDeviceHandle device, double duration_sec = 5.0)
// 线程安全队列(参考 ROS publisher 的 read_loop + publish_callback 分离模式)
std::mutex mtx;
std::queue<CFingerSample> queue;
std::queue<std::vector<uint8_t>> raw_queue;
bool running = true;
// 读取线程:持续从设备读取 sample 放入队列
// 读取线程:持续从设备读取 sample 和原始帧放入队列
std::thread read_thread([&]() {
while (running) {
CFingerSample sample;
memset(&sample, 0, sizeof(sample));
auto e = eskin_read_sample(device, 50, &sample);
if (e == ESkinSuccess) {
uint8_t raw_buf[512] = {};
uint32_t raw_len = 0;
auto raw_err = eskin_read_stream_frame(
device, 1, raw_buf, sizeof(raw_buf), &raw_len);
std::vector<uint8_t> raw_frame;
if (raw_err == ESkinSuccess) {
raw_frame.assign(raw_buf, raw_buf + std::min<uint32_t>(raw_len, sizeof(raw_buf)));
}
std::lock_guard<std::mutex> lock(mtx);
queue.push(sample);
raw_queue.push(std::move(raw_frame));
while (queue.size() > 100) {
queue.pop(); // 防止堆积
}
while (raw_queue.size() > 100) {
raw_queue.pop();
}
}
// 超时等非致命错误忽略,继续读取
}
@@ -96,11 +112,18 @@ static void demo_streaming(EskinDeviceHandle device, double duration_sec = 5.0)
std::lock_guard<std::mutex> lock(mtx);
while (!queue.empty()) {
const auto &s = queue.front();
printf("[%5u] module=%u fx=%u fy=%u fz=%u\n",
size_t raw_len = 0;
if (!raw_queue.empty()) {
raw_len = raw_queue.front().size();
raw_queue.pop();
}
printf("[%5u] module=%u fx=%u fy=%u fz=%u raw_len=%zu\n",
s.sequence, s.combined_force.module,
s.combined_force.force.fx,
s.combined_force.force.fy,
s.combined_force.force.fz);
s.combined_force.force.fz,
raw_len);
queue.pop();
count++;
}
@@ -145,4 +168,4 @@ int main(int argc, char *argv[]) {
eskin_close(device);
printf("Device closed\n");
return 0;
}
}

View File

@@ -126,6 +126,11 @@ class EskinDevice:
c_void_p, c_uint32, POINTER(CFingerSample)
]
lib.eskin_read_stream_frame.restype = c_uint32
lib.eskin_read_stream_frame.argtypes = [
c_void_p, c_uint32, POINTER(c_uint8), c_uint32, POINTER(c_uint32)
]
lib.eskin_get_mode.restype = c_uint32
lib.eskin_get_mode.argtypes = [c_void_p, POINTER(c_uint32)]
@@ -271,6 +276,17 @@ class EskinDevice:
raise RuntimeError(f"read_sample failed: error={err}")
return sample
def read_stream_frame(self, timeout_ms: int = 200, max_len: int = 512) -> bytes:
"""读取一个 stream 原始完整协议帧(流模式下调用)"""
buf = (c_uint8 * max_len)()
actual = c_uint32(0)
err = self._lib.eskin_read_stream_frame(
self._handle, timeout_ms, buf, len(buf), ctypes.byref(actual)
)
if err != 0:
raise RuntimeError(f"read_stream_frame failed: error={err}")
return bytes(buf[:min(actual.value, len(buf))])
def get_mode(self) -> int:
"""查询当前设备模式0=Command, 1=Streaming"""
out = c_uint32(0)
@@ -283,4 +299,4 @@ class EskinDevice:
return self
def __exit__(self, *args):
self.close()
self.close()

View File

@@ -33,14 +33,17 @@ def demo_streaming(dev: EskinDevice, duration_sec: float = 5.0):
# 线程安全的队列(参考 ROS demo 的 read_loop + publish_callback 分离模式)
queue: deque = deque(maxlen=100)
raw_queue: deque = deque(maxlen=100)
running = True
def read_loop():
"""独立读取线程:持续从设备读取 sample"""
"""独立读取线程:持续从设备读取 sample 和原始帧"""
while running:
try:
sample = dev.read_sample(timeout_ms=50)
queue.append(sample)
raw_frame = dev.read_stream_frame(timeout_ms=1)
raw_queue.append(raw_frame)
except RuntimeError:
# 超时等非致命错误,继续读取
pass
@@ -55,12 +58,14 @@ def demo_streaming(dev: EskinDevice, duration_sec: float = 5.0):
while time.monotonic() - start < duration_sec:
if queue:
sample: CFingerSample = queue.popleft()
raw_frame = raw_queue.popleft() if raw_queue else b""
f = sample.combined_force.force
mod = sample.combined_force.module
print(
f"[{sample.sequence:5d}] "
f"module={mod} "
f"fx={f.fx} fy={f.fy} fz={f.fz}"
f"fx={f.fx} fy={f.fy} fz={f.fz} "
f"raw_len={len(raw_frame)}"
)
count += 1
else:
@@ -89,4 +94,4 @@ def main():
if __name__ == "__main__":
main()
main()