imprintx 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- imprintx-0.2.0/LICENSE +52 -0
- imprintx-0.2.0/PKG-INFO +168 -0
- imprintx-0.2.0/README_PYPI.md +156 -0
- imprintx-0.2.0/api/.cargo/config.toml +2 -0
- imprintx-0.2.0/api/Cargo.lock +1277 -0
- imprintx-0.2.0/api/Cargo.toml +34 -0
- imprintx-0.2.0/api/build.rs +8 -0
- imprintx-0.2.0/api/build_win.bat +41 -0
- imprintx-0.2.0/api/build_win.ps1 +40 -0
- imprintx-0.2.0/api/src/context.rs +627 -0
- imprintx-0.2.0/api/src/encoder.rs +400 -0
- imprintx-0.2.0/api/src/inference.rs +510 -0
- imprintx-0.2.0/api/src/lib.rs +710 -0
- imprintx-0.2.0/api/src/parser.rs +377 -0
- imprintx-0.2.0/api/src/protocol.rs +119 -0
- imprintx-0.2.0/api/src/python/mod.rs +39 -0
- imprintx-0.2.0/api/src/python/py_glove.rs +875 -0
- imprintx-0.2.0/api/src/python/py_types.rs +161 -0
- imprintx-0.2.0/api/src/serial_io.rs +116 -0
- imprintx-0.2.0/api/test_unit.c +982 -0
- imprintx-0.2.0/api/touch_glove_api.c +1769 -0
- imprintx-0.2.0/api/touch_glove_api.h +313 -0
- imprintx-0.2.0/api/touch_glove_api_test.h +30 -0
- imprintx-0.2.0/pyproject.toml +31 -0
- imprintx-0.2.0/python/imprintx/__init__.py +231 -0
imprintx-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
================================================================================
|
|
2
|
+
TOUCH GLOVE SDK LICENSE & PROPRIETARY CLAIMS
|
|
3
|
+
================================================================================
|
|
4
|
+
Version: v1.1.0
|
|
5
|
+
Release Date: 2026-07-14
|
|
6
|
+
Last Modified: 2026-07-14 13:57:00 (Asia/Shanghai)
|
|
7
|
+
Author/Owner: ImprintX
|
|
8
|
+
Copyright: Copyright (c) 2026 ImprintX. All Rights Reserved.
|
|
9
|
+
|
|
10
|
+
--------------------------------------------------------------------------------
|
|
11
|
+
1. PROPRIETARY RIGHTS & CONFIDENTIALITY
|
|
12
|
+
--------------------------------------------------------------------------------
|
|
13
|
+
This software development kit (SDK), including but not limited to the compiled
|
|
14
|
+
dynamic libraries (libtouch_glove.so), C API header files (touch_glove_api.h),
|
|
15
|
+
source code, algorithms, logic, and python examples (example.py), contains
|
|
16
|
+
valuable trade secrets, intellectual property, and proprietary technologies
|
|
17
|
+
owned exclusively by ImprintX.
|
|
18
|
+
|
|
19
|
+
This SDK is protected by copyright laws, international treaty provisions, and
|
|
20
|
+
other applicable intellectual property and proprietary rights laws.
|
|
21
|
+
|
|
22
|
+
--------------------------------------------------------------------------------
|
|
23
|
+
2. INTELLECTUAL PROPERTY CLAIMS
|
|
24
|
+
--------------------------------------------------------------------------------
|
|
25
|
+
ImprintX claims all intellectual property rights, patent rights, and trade
|
|
26
|
+
secret rights in:
|
|
27
|
+
- The serial communication protocol and multi-channel packet framing logic.
|
|
28
|
+
- The Precision Time Protocol (PTP IEEE 1588) hardware clock integration.
|
|
29
|
+
- The multi-channel real-time tactile image queue parsing and ring-buffer logic.
|
|
30
|
+
- The dense tactile multitask ONNX model inference engine including the
|
|
31
|
+
zero-point tare offset calibration methods, contact threshold filtering,
|
|
32
|
+
and normal pressure physical constraints.
|
|
33
|
+
|
|
34
|
+
--------------------------------------------------------------------------------
|
|
35
|
+
3. TERMS OF USE
|
|
36
|
+
--------------------------------------------------------------------------------
|
|
37
|
+
- Permission is hereby granted to authorized users/customers of the Touch Glove
|
|
38
|
+
products to use, integrate, and execute this SDK solely in connection with
|
|
39
|
+
official Touch Glove hardware devices.
|
|
40
|
+
- Modification, reverse-engineering, decompilation, decryption, or disassembly
|
|
41
|
+
of the precompiled dynamic libraries (libtouch_glove.so) is strictly prohibited.
|
|
42
|
+
- Redistribution of the SDK, in whole or in part, to unauthorized third parties
|
|
43
|
+
without prior written consent from ImprintX is strictly prohibited.
|
|
44
|
+
|
|
45
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
46
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
47
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
48
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
49
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
50
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
51
|
+
SOFTWARE.
|
|
52
|
+
================================================================================
|
imprintx-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: imprintx
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Requires-Dist: numpy >=1.20.0
|
|
5
|
+
License-File: LICENSE
|
|
6
|
+
Summary: ImprintX Tactile SDK - Python bindings
|
|
7
|
+
Author: ImprintX
|
|
8
|
+
License: Proprietary
|
|
9
|
+
Requires-Python: >=3.8
|
|
10
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
11
|
+
|
|
12
|
+
# TouchGlove SDK
|
|
13
|
+
|
|
14
|
+
High-performance Python SDK for **Touch Glove** 5-channel tactile data acquisition, RTC time synchronization, real-time 3D displacement/force physical inference (ONNX Runtime / OpenVINO), and H.265 video recording with microsecond-level timestamps.
|
|
15
|
+
|
|
16
|
+
Powered by a native Rust core with high-efficiency PyO3 bindings.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## ⚡ Quick Start
|
|
21
|
+
|
|
22
|
+
### Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pip install imprintx
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Basic Streaming Example
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from imprintx import TouchGlove, list_ports
|
|
32
|
+
import time
|
|
33
|
+
|
|
34
|
+
# Scan for available serial ports
|
|
35
|
+
ports = list_ports()
|
|
36
|
+
print("Available ports:", ports)
|
|
37
|
+
|
|
38
|
+
if not ports:
|
|
39
|
+
raise RuntimeError("No serial ports found!")
|
|
40
|
+
|
|
41
|
+
# Connect to glove device and start streaming
|
|
42
|
+
with TouchGlove(port=ports[0]) as glove:
|
|
43
|
+
print("Device SN:", glove.get_sn())
|
|
44
|
+
glove.sync_rtc() # Synchronize host clock with hardware RTC
|
|
45
|
+
glove.start()
|
|
46
|
+
|
|
47
|
+
print("Streaming tactile data... Press Ctrl+C to stop.")
|
|
48
|
+
while True:
|
|
49
|
+
batch = glove.poll()
|
|
50
|
+
for frame in batch:
|
|
51
|
+
print(f"Ch {frame.channel} | Seq: {frame.seq_id} | Timestamp: {frame.timestamp_us} us | Image: {frame.image.shape}")
|
|
52
|
+
time.sleep(0.01)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## ✨ Features
|
|
58
|
+
|
|
59
|
+
- **High-Throughput 5-Channel Streaming**: Concurrent acquisition of 192x192 8-bit tactile images across 5 channels.
|
|
60
|
+
- **Hardware RTC Synchronization**: Precision clock alignment between host OS and glove hardware RTC.
|
|
61
|
+
- **Real-Time Physical Inference**: ONNX Runtime and OpenVINO inference for 3D displacement fields `(32, 32, 3)` and 3D force fields `(32, 32, 3)` with auto baseline calibration.
|
|
62
|
+
- **H.265 Video Recording & Microsecond Timestamps**: High-efficiency HEVC grid video encoding + microsecond timestamp JSON export.
|
|
63
|
+
- **Cross-Platform Support**: Native binaries for Linux (`x86_64`, `aarch64`), Windows, and macOS.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 📖 Key Python APIs
|
|
68
|
+
|
|
69
|
+
### 1. `TouchGlove` Class
|
|
70
|
+
|
|
71
|
+
Main interface for device management, data acquisition, and inference.
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
glove = TouchGlove(
|
|
75
|
+
port="/dev/ttyACM0", # Serial port path
|
|
76
|
+
model="dense_3ch.onnx", # Path to ONNX model (optional)
|
|
77
|
+
device="auto", # "auto", "cuda", "gpu", "npu", "cpu", "mac"
|
|
78
|
+
auto_open=True # Auto handshake on initialization
|
|
79
|
+
)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
#### Methods
|
|
83
|
+
|
|
84
|
+
- **Device Management**:
|
|
85
|
+
- `glove.open(port: str)` / `glove.close()`: Manage serial connection.
|
|
86
|
+
- `glove.start()` / `glove.stop()`: Start / stop tactile data stream.
|
|
87
|
+
- `glove.poll() -> FrameBatch`: Fetch latest batch of 5-channel tactile frames.
|
|
88
|
+
- `glove.is_open() -> bool` / `glove.is_streaming() -> bool`: Query connection status.
|
|
89
|
+
|
|
90
|
+
- **Baseline Calibration & Inference**:
|
|
91
|
+
- `glove.calibrate_baseline(duration_sec=1.0)`: Capture baseline and calibrate zero point for live inference.
|
|
92
|
+
- `glove.get_dense_fields()`: Get latest 5-channel 3D displacement and force fields `(5, 32, 32, 3)`.
|
|
93
|
+
|
|
94
|
+
- **Hardware SN & RTC**:
|
|
95
|
+
- `glove.get_sn() -> str`: Query hardware serial number (SN).
|
|
96
|
+
- `glove.set_sn(sn: str) -> bool`: Write hardware serial number.
|
|
97
|
+
- `glove.sync_rtc() -> bool`: Sync host OS system time to glove RTC.
|
|
98
|
+
- `glove.query_rtc() -> Optional[str]`: Query current glove RTC timestamp string.
|
|
99
|
+
|
|
100
|
+
- **Video Recording**:
|
|
101
|
+
- `glove.start_recording(output_path, fps=30.0, crf=18)`: Record 5-channel grid H.265 video.
|
|
102
|
+
- `glove.stop_recording() -> str`: Stop recording and generate microsecond timestamp JSON file.
|
|
103
|
+
|
|
104
|
+
### 2. `Frame` Class
|
|
105
|
+
|
|
106
|
+
Represents a single frame from one channel.
|
|
107
|
+
|
|
108
|
+
- `frame.channel`: Channel index (`0`–`4`).
|
|
109
|
+
- `frame.sensor_id`: Hexadecimal sensor hardware ID.
|
|
110
|
+
- `frame.seq_id`: Frame sequence number.
|
|
111
|
+
- `frame.timestamp_us`: Hardware reception timestamp in microseconds.
|
|
112
|
+
- `frame.image`: Raw tactile image as `numpy.ndarray` (`shape=(192, 192), dtype=uint8`).
|
|
113
|
+
- `frame.disp`: Inferred 3D displacement field (`shape=(32, 32, 3), dtype=float32`, optional).
|
|
114
|
+
- `frame.force_field`: Inferred 3D force field (`shape=(32, 32, 3), dtype=float32`, optional).
|
|
115
|
+
|
|
116
|
+
### 3. `FrameBatch` Class
|
|
117
|
+
|
|
118
|
+
Synchronized batch containing frames across all 5 channels.
|
|
119
|
+
|
|
120
|
+
- `batch.frames`: List of 5 `Frame` objects (or `None` for inactive channels).
|
|
121
|
+
- `batch.timestamp`: Host Unix timestamp (seconds).
|
|
122
|
+
- `batch.total_frames`: Count of valid frames in batch.
|
|
123
|
+
- Supports iteration: `for frame in batch: ...`
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 🛠 Advanced Examples
|
|
128
|
+
|
|
129
|
+
### Model Inference with Baseline Calibration
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from imprintx import TouchGlove, list_ports
|
|
133
|
+
import time
|
|
134
|
+
|
|
135
|
+
ports = list_ports()
|
|
136
|
+
with TouchGlove(port=ports[0], model="dense_3ch.onnx", device="cuda") as glove:
|
|
137
|
+
glove.start()
|
|
138
|
+
|
|
139
|
+
print("Calibrating baseline for 1 second...")
|
|
140
|
+
glove.calibrate_baseline(duration_sec=1.0)
|
|
141
|
+
print("Calibration complete!")
|
|
142
|
+
|
|
143
|
+
while True:
|
|
144
|
+
batch = glove.poll()
|
|
145
|
+
for frame in batch:
|
|
146
|
+
if frame.disp is not None and frame.force_field is not None:
|
|
147
|
+
print(f"Ch {frame.channel} Max Force: {frame.force_field.max():.2f}")
|
|
148
|
+
time.sleep(0.01)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Video Recording & Timestamp Query
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
from imprintx import TouchGlove, list_ports, load_video_timestamps
|
|
155
|
+
import time
|
|
156
|
+
|
|
157
|
+
ports = list_ports()
|
|
158
|
+
with TouchGlove(port=ports[0]) as glove:
|
|
159
|
+
glove.start()
|
|
160
|
+
glove.start_recording("tactile_recording.mp4", fps=30)
|
|
161
|
+
time.sleep(5.0) # Record 5 seconds
|
|
162
|
+
glove.stop_recording()
|
|
163
|
+
|
|
164
|
+
# Parse exported microsecond timestamps
|
|
165
|
+
records = load_video_timestamps("tactile_recording.mp4.json")
|
|
166
|
+
print(f"Total recorded frames: {len(records)}")
|
|
167
|
+
```
|
|
168
|
+
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# TouchGlove SDK
|
|
2
|
+
|
|
3
|
+
High-performance Python SDK for **Touch Glove** 5-channel tactile data acquisition, RTC time synchronization, real-time 3D displacement/force physical inference (ONNX Runtime / OpenVINO), and H.265 video recording with microsecond-level timestamps.
|
|
4
|
+
|
|
5
|
+
Powered by a native Rust core with high-efficiency PyO3 bindings.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## ⚡ Quick Start
|
|
10
|
+
|
|
11
|
+
### Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install imprintx
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Basic Streaming Example
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from imprintx import TouchGlove, list_ports
|
|
21
|
+
import time
|
|
22
|
+
|
|
23
|
+
# Scan for available serial ports
|
|
24
|
+
ports = list_ports()
|
|
25
|
+
print("Available ports:", ports)
|
|
26
|
+
|
|
27
|
+
if not ports:
|
|
28
|
+
raise RuntimeError("No serial ports found!")
|
|
29
|
+
|
|
30
|
+
# Connect to glove device and start streaming
|
|
31
|
+
with TouchGlove(port=ports[0]) as glove:
|
|
32
|
+
print("Device SN:", glove.get_sn())
|
|
33
|
+
glove.sync_rtc() # Synchronize host clock with hardware RTC
|
|
34
|
+
glove.start()
|
|
35
|
+
|
|
36
|
+
print("Streaming tactile data... Press Ctrl+C to stop.")
|
|
37
|
+
while True:
|
|
38
|
+
batch = glove.poll()
|
|
39
|
+
for frame in batch:
|
|
40
|
+
print(f"Ch {frame.channel} | Seq: {frame.seq_id} | Timestamp: {frame.timestamp_us} us | Image: {frame.image.shape}")
|
|
41
|
+
time.sleep(0.01)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## ✨ Features
|
|
47
|
+
|
|
48
|
+
- **High-Throughput 5-Channel Streaming**: Concurrent acquisition of 192x192 8-bit tactile images across 5 channels.
|
|
49
|
+
- **Hardware RTC Synchronization**: Precision clock alignment between host OS and glove hardware RTC.
|
|
50
|
+
- **Real-Time Physical Inference**: ONNX Runtime and OpenVINO inference for 3D displacement fields `(32, 32, 3)` and 3D force fields `(32, 32, 3)` with auto baseline calibration.
|
|
51
|
+
- **H.265 Video Recording & Microsecond Timestamps**: High-efficiency HEVC grid video encoding + microsecond timestamp JSON export.
|
|
52
|
+
- **Cross-Platform Support**: Native binaries for Linux (`x86_64`, `aarch64`), Windows, and macOS.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 📖 Key Python APIs
|
|
57
|
+
|
|
58
|
+
### 1. `TouchGlove` Class
|
|
59
|
+
|
|
60
|
+
Main interface for device management, data acquisition, and inference.
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
glove = TouchGlove(
|
|
64
|
+
port="/dev/ttyACM0", # Serial port path
|
|
65
|
+
model="dense_3ch.onnx", # Path to ONNX model (optional)
|
|
66
|
+
device="auto", # "auto", "cuda", "gpu", "npu", "cpu", "mac"
|
|
67
|
+
auto_open=True # Auto handshake on initialization
|
|
68
|
+
)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
#### Methods
|
|
72
|
+
|
|
73
|
+
- **Device Management**:
|
|
74
|
+
- `glove.open(port: str)` / `glove.close()`: Manage serial connection.
|
|
75
|
+
- `glove.start()` / `glove.stop()`: Start / stop tactile data stream.
|
|
76
|
+
- `glove.poll() -> FrameBatch`: Fetch latest batch of 5-channel tactile frames.
|
|
77
|
+
- `glove.is_open() -> bool` / `glove.is_streaming() -> bool`: Query connection status.
|
|
78
|
+
|
|
79
|
+
- **Baseline Calibration & Inference**:
|
|
80
|
+
- `glove.calibrate_baseline(duration_sec=1.0)`: Capture baseline and calibrate zero point for live inference.
|
|
81
|
+
- `glove.get_dense_fields()`: Get latest 5-channel 3D displacement and force fields `(5, 32, 32, 3)`.
|
|
82
|
+
|
|
83
|
+
- **Hardware SN & RTC**:
|
|
84
|
+
- `glove.get_sn() -> str`: Query hardware serial number (SN).
|
|
85
|
+
- `glove.set_sn(sn: str) -> bool`: Write hardware serial number.
|
|
86
|
+
- `glove.sync_rtc() -> bool`: Sync host OS system time to glove RTC.
|
|
87
|
+
- `glove.query_rtc() -> Optional[str]`: Query current glove RTC timestamp string.
|
|
88
|
+
|
|
89
|
+
- **Video Recording**:
|
|
90
|
+
- `glove.start_recording(output_path, fps=30.0, crf=18)`: Record 5-channel grid H.265 video.
|
|
91
|
+
- `glove.stop_recording() -> str`: Stop recording and generate microsecond timestamp JSON file.
|
|
92
|
+
|
|
93
|
+
### 2. `Frame` Class
|
|
94
|
+
|
|
95
|
+
Represents a single frame from one channel.
|
|
96
|
+
|
|
97
|
+
- `frame.channel`: Channel index (`0`–`4`).
|
|
98
|
+
- `frame.sensor_id`: Hexadecimal sensor hardware ID.
|
|
99
|
+
- `frame.seq_id`: Frame sequence number.
|
|
100
|
+
- `frame.timestamp_us`: Hardware reception timestamp in microseconds.
|
|
101
|
+
- `frame.image`: Raw tactile image as `numpy.ndarray` (`shape=(192, 192), dtype=uint8`).
|
|
102
|
+
- `frame.disp`: Inferred 3D displacement field (`shape=(32, 32, 3), dtype=float32`, optional).
|
|
103
|
+
- `frame.force_field`: Inferred 3D force field (`shape=(32, 32, 3), dtype=float32`, optional).
|
|
104
|
+
|
|
105
|
+
### 3. `FrameBatch` Class
|
|
106
|
+
|
|
107
|
+
Synchronized batch containing frames across all 5 channels.
|
|
108
|
+
|
|
109
|
+
- `batch.frames`: List of 5 `Frame` objects (or `None` for inactive channels).
|
|
110
|
+
- `batch.timestamp`: Host Unix timestamp (seconds).
|
|
111
|
+
- `batch.total_frames`: Count of valid frames in batch.
|
|
112
|
+
- Supports iteration: `for frame in batch: ...`
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 🛠 Advanced Examples
|
|
117
|
+
|
|
118
|
+
### Model Inference with Baseline Calibration
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
from imprintx import TouchGlove, list_ports
|
|
122
|
+
import time
|
|
123
|
+
|
|
124
|
+
ports = list_ports()
|
|
125
|
+
with TouchGlove(port=ports[0], model="dense_3ch.onnx", device="cuda") as glove:
|
|
126
|
+
glove.start()
|
|
127
|
+
|
|
128
|
+
print("Calibrating baseline for 1 second...")
|
|
129
|
+
glove.calibrate_baseline(duration_sec=1.0)
|
|
130
|
+
print("Calibration complete!")
|
|
131
|
+
|
|
132
|
+
while True:
|
|
133
|
+
batch = glove.poll()
|
|
134
|
+
for frame in batch:
|
|
135
|
+
if frame.disp is not None and frame.force_field is not None:
|
|
136
|
+
print(f"Ch {frame.channel} Max Force: {frame.force_field.max():.2f}")
|
|
137
|
+
time.sleep(0.01)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Video Recording & Timestamp Query
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
from imprintx import TouchGlove, list_ports, load_video_timestamps
|
|
144
|
+
import time
|
|
145
|
+
|
|
146
|
+
ports = list_ports()
|
|
147
|
+
with TouchGlove(port=ports[0]) as glove:
|
|
148
|
+
glove.start()
|
|
149
|
+
glove.start_recording("tactile_recording.mp4", fps=30)
|
|
150
|
+
time.sleep(5.0) # Record 5 seconds
|
|
151
|
+
glove.stop_recording()
|
|
152
|
+
|
|
153
|
+
# Parse exported microsecond timestamps
|
|
154
|
+
records = load_video_timestamps("tactile_recording.mp4.json")
|
|
155
|
+
print(f"Total recorded frames: {len(records)}")
|
|
156
|
+
```
|