Metadata-Version: 2.4
Name: imprintx
Version: 0.2.0
Requires-Dist: numpy >=1.20.0
License-File: LICENSE
Summary: ImprintX Tactile SDK - Python bindings
Author: ImprintX
License: Proprietary
Requires-Python: >=3.8
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM

# TouchGlove SDK

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.

Powered by a native Rust core with high-efficiency PyO3 bindings.

---

## ⚡ Quick Start

### Installation

```bash
pip install imprintx
```

### Basic Streaming Example

```python
from imprintx import TouchGlove, list_ports
import time

# Scan for available serial ports
ports = list_ports()
print("Available ports:", ports)

if not ports:
    raise RuntimeError("No serial ports found!")

# Connect to glove device and start streaming
with TouchGlove(port=ports[0]) as glove:
    print("Device SN:", glove.get_sn())
    glove.sync_rtc()  # Synchronize host clock with hardware RTC
    glove.start()

    print("Streaming tactile data... Press Ctrl+C to stop.")
    while True:
        batch = glove.poll()
        for frame in batch:
            print(f"Ch {frame.channel} | Seq: {frame.seq_id} | Timestamp: {frame.timestamp_us} us | Image: {frame.image.shape}")
        time.sleep(0.01)
```

---

## ✨ Features

- **High-Throughput 5-Channel Streaming**: Concurrent acquisition of 192x192 8-bit tactile images across 5 channels.
- **Hardware RTC Synchronization**: Precision clock alignment between host OS and glove hardware RTC.
- **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.
- **H.265 Video Recording & Microsecond Timestamps**: High-efficiency HEVC grid video encoding + microsecond timestamp JSON export.
- **Cross-Platform Support**: Native binaries for Linux (`x86_64`, `aarch64`), Windows, and macOS.

---

## 📖 Key Python APIs

### 1. `TouchGlove` Class

Main interface for device management, data acquisition, and inference.

```python
glove = TouchGlove(
    port="/dev/ttyACM0",     # Serial port path
    model="dense_3ch.onnx", # Path to ONNX model (optional)
    device="auto",           # "auto", "cuda", "gpu", "npu", "cpu", "mac"
    auto_open=True           # Auto handshake on initialization
)
```

#### Methods

- **Device Management**:
  - `glove.open(port: str)` / `glove.close()`: Manage serial connection.
  - `glove.start()` / `glove.stop()`: Start / stop tactile data stream.
  - `glove.poll() -> FrameBatch`: Fetch latest batch of 5-channel tactile frames.
  - `glove.is_open() -> bool` / `glove.is_streaming() -> bool`: Query connection status.

- **Baseline Calibration & Inference**:
  - `glove.calibrate_baseline(duration_sec=1.0)`: Capture baseline and calibrate zero point for live inference.
  - `glove.get_dense_fields()`: Get latest 5-channel 3D displacement and force fields `(5, 32, 32, 3)`.

- **Hardware SN & RTC**:
  - `glove.get_sn() -> str`: Query hardware serial number (SN).
  - `glove.set_sn(sn: str) -> bool`: Write hardware serial number.
  - `glove.sync_rtc() -> bool`: Sync host OS system time to glove RTC.
  - `glove.query_rtc() -> Optional[str]`: Query current glove RTC timestamp string.

- **Video Recording**:
  - `glove.start_recording(output_path, fps=30.0, crf=18)`: Record 5-channel grid H.265 video.
  - `glove.stop_recording() -> str`: Stop recording and generate microsecond timestamp JSON file.

### 2. `Frame` Class

Represents a single frame from one channel.

- `frame.channel`: Channel index (`0`–`4`).
- `frame.sensor_id`: Hexadecimal sensor hardware ID.
- `frame.seq_id`: Frame sequence number.
- `frame.timestamp_us`: Hardware reception timestamp in microseconds.
- `frame.image`: Raw tactile image as `numpy.ndarray` (`shape=(192, 192), dtype=uint8`).
- `frame.disp`: Inferred 3D displacement field (`shape=(32, 32, 3), dtype=float32`, optional).
- `frame.force_field`: Inferred 3D force field (`shape=(32, 32, 3), dtype=float32`, optional).

### 3. `FrameBatch` Class

Synchronized batch containing frames across all 5 channels.

- `batch.frames`: List of 5 `Frame` objects (or `None` for inactive channels).
- `batch.timestamp`: Host Unix timestamp (seconds).
- `batch.total_frames`: Count of valid frames in batch.
- Supports iteration: `for frame in batch: ...`

---

## 🛠 Advanced Examples

### Model Inference with Baseline Calibration

```python
from imprintx import TouchGlove, list_ports
import time

ports = list_ports()
with TouchGlove(port=ports[0], model="dense_3ch.onnx", device="cuda") as glove:
    glove.start()
    
    print("Calibrating baseline for 1 second...")
    glove.calibrate_baseline(duration_sec=1.0)
    print("Calibration complete!")
    
    while True:
        batch = glove.poll()
        for frame in batch:
            if frame.disp is not None and frame.force_field is not None:
                print(f"Ch {frame.channel} Max Force: {frame.force_field.max():.2f}")
        time.sleep(0.01)
```

### Video Recording & Timestamp Query

```python
from imprintx import TouchGlove, list_ports, load_video_timestamps
import time

ports = list_ports()
with TouchGlove(port=ports[0]) as glove:
    glove.start()
    glove.start_recording("tactile_recording.mp4", fps=30)
    time.sleep(5.0)  # Record 5 seconds
    glove.stop_recording()

# Parse exported microsecond timestamps
records = load_video_timestamps("tactile_recording.mp4.json")
print(f"Total recorded frames: {len(records)}")
```

