Skip to main content

ImprintX SDK (Python)

Python SDK for Imprint X and Imprint Glove. Imprint X support provides event-stream acquisition and device control. Imprint Glove support provides synchronized five-channel tactile image acquisition, raw IMU data, device-state control, and data streaming.

The SDK distinguishes the devices as sensor and glove in module names and the service's --device option. The Python classes remain Sensor and TouchGlove.

The SDK supports Python 3.8 and newer. The package includes resident Imprint Glove button recording; model inference, GUI, and example programs are not included. Python dependencies are NumPy/PyZMQ and the bundled Rust extension. Automatic Glove recording also requires a system FFmpeg executable with a working libx265 encoder on PATH; startup checks this before enabling recording. Communication-only mode and Imprint X do not require FFmpeg.

What's New in 0.3.2

  1. Imprint X events are stored in a fixed ring with a global event index and read through read-only events(start, end) and slots(start, end) snapshots, replacing batch polling. Service batches carry start/end indices, and gaps show overwritten events.
  2. EVT20 decode errors and timestamp jumps are reported in sensor.stats and the service STATUS reply.
  3. imprintx-sdk --device glove now defaults to resident button recording in recordings/; use --no-record for communication only or an external recording controller. The shared Glove client and recorder are included in the package.

Installation

pip install imprintx

Imprint X

Shared mode (the service owns the serial port):

imprintx-sdk --device sensor /dev/ttyACM0

Direct mode (the application owns the serial port; do not run the service for the same device at the same time):

from imprintx.sensor import Sensor

with Sensor("/dev/ttyACM0") as sensor:
    sensor.set_light(True)
    try:
        start = sensor.events_written
        sensor.start()
        end = sensor.wait_for_events(start, timeout_sec=1.0)
        if end == start:
            raise TimeoutError("No events received")

        events = sensor.events(start, end)
        print(events["x"], events["y"], events["polarity"], events["timestamp_us"])
    finally:
        try:
            if sensor.is_streaming:
                sensor.stop()
        finally:
            if not sensor.is_streaming:
                sensor.set_light(False)

Imprint X events include 320 x 320 coordinates, polarity, and a device timestamp in microseconds. Acquisition and decoding follow evtcap: starting stops previous output, waits 300 ms, clears old serial input, and enables capture. One resident reader reads up to 8 KiB at a time. The event ring holds 26,214 events (SENSOR_EVENT_CAPACITY); the completed-slot ring holds 500 slots (SENSOR_SLOT_CAPACITY). Both use global indices and overwrite their oldest items. events(start, end) and slots(start, end) return read-only NumPy snapshots copied under the reader's lock; returned arrays remain stable as capture continues. Events remain in serial arrival order. An increase in device milliseconds publishes the previous slot; stopping or ending the reader flushes the final nonempty slot. The decoder rejects regressing CD timestamps. A TIME_HIGH decrease adopts raw device time without unwrapping rollover; regressions in successfully decoded events count as timestamp_jumps and do not split slots. Decode failures count as decode_errors and resynchronize using evtcap's rules without stopping capture. events() returns an empty array if its start has been overwritten. slots() advances an overwritten start to the oldest slot whose events remain fully readable under the copy lock. Unwritten ends are clipped to the current count. Callers must check the returned length and global event indices to detect gaps.

The Sensor GUI example uses direct SDK access and evtcap's Python renderer by default. Each iteration consumes all newly completed slots. With events, it clears the image to gray, draws ON events white, then draws OFF events black; OFF wins when both polarities occur at the same pixel in one batch. With no new completed slots, it keeps the previous image. The window is 640 x 640 and reports the rate of rendered event batches as FPS. It uses waitKey(1) by default; --display-fps optionally limits refresh frequency. Events lost to ring overwrites are reported on exit. Explicit endpoints draw shared-service batches. To preserve raw streaming and recording, the service also publishes events in the slot still being filled; those batch boundaries differ from direct completed-slot rendering, and network buffering can still introduce latency.

The Sensor service coalesces events at roughly 5 ms intervals and sets send/receive queue high-water marks to one batch. Automatically launched private Sensor services use dynamically allocated loopback TCP ports so the small socket buffer settings take effect; libzmq does not apply those settings to IPC transports. High-water marks limit message queues, not all buffering along the transport. Backpressured event publication does not block the service loop: it retains the global read index and coalesces accumulated ring events on the next attempt. Events that can no longer be retained remain visible as index gaps; the messaging layer does not silently discard events. Explicit shared endpoints are unchanged. Slow subscribers still affect the shared service, and control replies share the event subscription channel, so subscribers should consume continuously.

Imprint Glove

Shared mode (the service owns the serial port and defaults to resident button recording):

imprintx-sdk --device glove /dev/ttyACM0

The first button press starts a segment; the service writes RECORDING only after the first real complete frame has been written. The second press stops recording, finalizes and saves the files, then restores CONNECTED and waits for the next segment. Each segment creates a unique MP4 in recordings/ under the current working directory, with matching _timestamps.json and _imu.json sidecars; existing files are never overwritten. Wait for RECORDING before pressing again. Ctrl+C exits while armed; during recording it saves the complete frames already received before closing the service. Wait for the next armed message after Saving recording... before starting another segment.

For communication only, or when another program owns recording state:

imprintx-sdk --device glove --no-record /dev/ttyACM0

The current reference firmware (ecf17ce) has a button-state defect: its first normal press reports recording end, and its toggle is not synchronized with host state changes or a forced stop. Firmware must fix this to guarantee the first-press start sequence above; the SDK preserves the state actually reported. Device-state writes change indicators; image and IMU streams use their own enable commands.

Only one recording controller may own a device's recording state. Glove examples use a communication-only service and share the packaged imprintx.glove.client and imprintx.glove.recording implementation. The repository command example/glove/record.py --button still saves one segment and exits; resident recording keeps waiting for further segments. Imprint X behavior is unchanged.

Direct mode (the application owns the serial port; do not run the service for the same device at the same time):

from imprintx.glove import TouchGlove

with TouchGlove("/dev/ttyACM0") as glove:
    print(f"Firmware: {glove.firmware_version}; device: {glove.sn}")
    glove.start()

    if not glove.wait_for_batch(timeout_sec=1.0):
        raise TimeoutError("No synchronized tactile batch received")

    batch = glove.poll()
    for frame in batch:
        print(
            f"channel={frame.channel} "
            f"timestamp={frame.timestamp_us}us "
            f"shape={frame.image.shape}"
        )

Glove IMU samples now follow the 24-byte firmware layout introduced in tacprint_dev commit b9bb433 (current firmware reference: ecf17ce). Each little-endian <QI6h sample contains unix_us, sensor_time, and six raw axes. The direct API, client NumPy views, binary messages, and recording JSON all retain unix_us. It is UTC Unix microseconds recorded by firmware after reading the IMU; 18446744073709551615 means no valid date anchor and is preserved unchanged. A valid date anchor alone does not prove synchronization with the host. The low 24 bits of sensor_time still provide the BMI088 clock and recording sample rate. Image and RTC calendars use fixed UTC+8; RTC synchronization and image timestamp conversion use that offset regardless of the host timezone. Setting RTC may change the common wall-clock timeline.

Compatibility: old firmware with 16-byte IMU samples is no longer supported. Upgrade firmware and update SDK services and clients together. The SDK does not guess the layout from payload length: 16-byte and 24-byte batches can have the same length. The connection handshake requires firmware V1.5 or newer. The old JSON IMU message fallback has been removed; imu messages always carry binary samples.

Up to three consecutive dropped synchronized batches are tolerated. Receive sequence gaps confirming more than three consecutive drops raise an error; a complete batch resets the count. Channel timestamps must still agree within 5 ms; missing images are not filled or combined across acquisition cycles. Receive counters cannot detect cycles the device never reports at all. The existing two-second timeout without a complete batch remains in effect.

Each image is a 192 x 192 NumPy array. A batch is returned only after the detected active tactile channels have been synchronized. Opening an Imprint Glove fails unless firmware version 1.5 or newer and the device identity are both validated. Unsupported firmware, invalid version responses and an unwritten SN raise explicit Chinese errors and abort the Glove connection. Timeouts report that the identity could not be read, without assuming its contents. Imprint X get_sn() also rejects an empty SN with a Chinese error. Internal provisioning can still write an SN to an unprovisioned device.

Examples

pps, fsync = glove.get_io_sync_status() reads DI 0x2F100300 and returns the tuple (pps, fsync). Each integer is 0 for invalid or 1 for valid. It works while idle or streaming; the shared-service equivalent is client.control(Control.GET_IO_SYNC_STATUS), which returns a JSON array [pps, fsync]. PPS and FSYNC validity are separate from the recording state at 0x2F100200. Unsupported firmware, malformed responses, and a one-second response timeout raise explicit errors rather than returning 0.

For usage examples, see the ImprintX SDK repository.

Data Integrity

Imprint X commands validate their checksums and acknowledgements; Imprint X event streams validate EVT20 types, coordinates, and timestamps. Imprint Glove streams validate checksums, payload sizes, hardware timestamps, and synchronized channel batches. Missing channels, timestamps, serial numbers, events, and frames are never fabricated. Queue overflow, malformed batches, timestamp regressions, and stream continuity failures beyond the three-batch allowance raise explicit errors; the SDK does not automatically reconnect or silently retry control requests.

License

Copyright (c) ImprintX. All rights reserved. This package is proprietary software; use and distribution are subject to the included license terms.

Glove firmware upgrade

Firmware image validation and USB OTG transfer are implemented in imprintx.glove.upgrade. This feature additionally requires pyserial>=3.5; install it separately or use the repository's example requirements. Stop the SDK service and other programs using the target serial port first. The device must have a matching preinstalled bootloader and support firmware transfer. Use an App .bin supplied for your hardware by the maintainer.

python -m imprintx.glove.upgrade /path/to/app.bin --check
python -m imprintx.glove.upgrade /path/to/app.bin --port /dev/ttyACM0

The repository's example/glove/upgrade.py calls this same implementation. Device identity and firmware build are checked after restart; failures are reported without automatic retransmission. Real-device upgrades, USB re-enumeration and power-loss recovery have not yet been validated.

Metadata

Release files for imprintx 0.3.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for imprintx 0.3.2
File Actions
imprintx-0.3.2-cp38-abi3-win_amd64.whl CPython 3.8 abi3 Windows x86-64 Details for imprintx-0.3.2-cp38-abi3-win_amd64.whl
imprintx-0.3.2-cp38-abi3-manylinux_2_34_x86_64.whl CPython 3.8 abi3 Linux glibc 2.34+ x86-64 Details for imprintx-0.3.2-cp38-abi3-manylinux_2_34_x86_64.whl
imprintx-0.3.2-cp38-abi3-manylinux_2_34_aarch64.whl CPython 3.8 abi3 Linux glibc 2.34+ ARM64 Details for imprintx-0.3.2-cp38-abi3-manylinux_2_34_aarch64.whl
imprintx-0.3.2-cp38-abi3-macosx_11_0_arm64.whl CPython 3.8 abi3 macOS 11.0+ ARM64 Details for imprintx-0.3.2-cp38-abi3-macosx_11_0_arm64.whl

Total release size: 2.1 MB

Release files / imprintx-0.3.2-cp38-abi3-win_amd64.whl

Download URL imprintx-0.3.2-cp38-abi3-win_amd64.whl
Size 372.1 kB
Tags CPython 3.8 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
da052b827b9a0968c5a3768ebd1415cd9ef604c1cc2e119235301bc5c2871b24
BLAKE2b-256 checksum
How to use checksums
bd73f6a00ab28c2eb60bcebe29df057e99f537e37fa664937a8ff6e5057b5d97
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.25

Release files / imprintx-0.3.2-cp38-abi3-manylinux_2_34_x86_64.whl

Download URL imprintx-0.3.2-cp38-abi3-manylinux_2_34_x86_64.whl
Size 651.0 kB
Tags CPython 3.8 Linux glibc 2.34+ x86-64 abi3
SHA-256 checksum
How to use checksums
1108aa14d09b077d97efbfa51cf8b551df2129debeb62683629d3327bd504a07
BLAKE2b-256 checksum
How to use checksums
6e752783534697487d6241f6fffef6a8c68ee5fcb2f4715ad8d9271d7fd96173
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.15.0

Release files / imprintx-0.3.2-cp38-abi3-manylinux_2_34_aarch64.whl

Download URL imprintx-0.3.2-cp38-abi3-manylinux_2_34_aarch64.whl
Size 635.0 kB
Tags CPython 3.8 Linux glibc 2.34+ ARM64 abi3
SHA-256 checksum
How to use checksums
ff272efa851464d9de00e33cde2aab48e4eb60e25095b5b8eff316ca1635f71d
BLAKE2b-256 checksum
How to use checksums
3b63356ad8a327d96a0c4756a4de0226d19f942dfbd687f715db6e628b35c4cd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / imprintx-0.3.2-cp38-abi3-macosx_11_0_arm64.whl

Download URL imprintx-0.3.2-cp38-abi3-macosx_11_0_arm64.whl
Size 487.7 kB
Tags CPython 3.8 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
450838ea46d566370632c921bce03be4fd1ba821ed462e96030c8677a03743eb
BLAKE2b-256 checksum
How to use checksums
5d453d1e18f92fac4490495523c92493ed5604ac951947676875fac5cab3eb07
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.25

Security for imprintx 0.3.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page