Skip to main content

Pure-Python Modbus TCP driver for the Inspire Robots RH56DFTP dexterous hand.

Project description

inspire_rh56dftp

Pure-Python Modbus TCP driver for the Inspire Robots RH56DFTP dexterous hand.

The official software stack ships only as a ROS package, which is heavy if all you want is to send 6 register values to a hand on the LAN. This package is just the wire protocol — three files, stdlib-only — plus a browser debug UI behind an optional dependency.

Manual: All register addresses, frame layouts and tactile map come from the official Inspire Robots RH56DFTP user manual PRJ-02-TS-U-010 V1.0.0 (Dec 2024). Section numbers (§2.6.20 etc.) in this codebase reference that document.

Install

pip install inspire_rh56dftp                # core driver only (no deps)
pip install inspire_rh56dftp[viz]           # + browser debug UI

Quick start

from inspire_rh56dftp import InspireHand

hand = InspireHand(ip="192.168.123.211")
hand.send_raw([0, 0, 0, 0, 0, 1000])       # close fist (thumb across palm)
hand.send_raw([1000, 1000, 1000, 1000, 1000, 0])   # open hand
hand.close()

Values are in DOF order: [pinky, ring, middle, index, thumb_bend, thumb_rotation], each 0..1000 (raw register units, 1000 = fully extended for the 4 fingers and thumb_bend; for thumb_rotation, 0 = retracted, 1000 = across palm).

Hardware setup

The RH56DFTP ships with factory-default IP 192.168.123.211 and exposes Modbus TCP on port 6000. It does not run a DHCP server, so the host needs a static IP in the same subnet:

sudo ip addr add 192.168.123.50/24 dev <eth>     # one-shot
# or persist via NetworkManager:
sudo nmcli con add type ethernet ifname <eth> con-name inspire-hand \
    ipv4.addresses 192.168.123.50/24 ipv4.method manual ipv6.method disabled

Verify:

ping -c 3 192.168.123.211

Two layers of API

InspireHand (client.py)         InspireHandSender (scheduler.py)
──────────────────────          ──────────────────────────────────
synchronous:                    background-thread wrapper around an
every call blocks until         InspireHand. Runs writes (control)
the hand acks                   and reads (tactile) on independent
                                clocks sharing one TCP socket.
use for: scripts,               use for: real-time control loops
one-shot moves,                 that also need continuous tactile
sequenced demos                 data

Both share the same lock on the underlying socket, so reads and writes never race on the wire even when issued from multiple threads.

Reading registers directly

The high-level API exposes send_raw() (writes ANGLE_SET) and the scheduler's latest_tactile. For everything else (joint feedback, force, custom ranges):

from inspire_rh56dftp import InspireHand, registers

hand = InspireHand(ip="192.168.123.211")
actual_angles = hand.read_holding(registers.ANGLE_ACT, 6)   # 6 ints
forces        = hand.read_holding(registers.FORCE_ACT, 6)

registers.py is a pure transcription of manual §2.6 — see the file or import it for the full address map.

Browser debug UI

pip install inspire_rh56dftp[viz]
python -m inspire_rh56dftp.viz 192.168.123.211      # IP defaults to factory
# open http://127.0.0.1:8765

The page has 6 horizontal sliders (one per DOF) and the live tactile heatmap laid out anatomically over a right-hand silhouette. Drag a slider to set the target; the orange "ack" number shows what the hand reports back. Useful for verifying wiring, finding mechanical stops, and watching tactile cells light up while you poke them.

The UI talks to the server over a single bidirectional WebSocket and works with the hand absent — sliders just won't move anything until you click Reconnect.

Modbus protocol quirks (read this before writing your own client)

These cost real time to discover; documenting them here so the next person doesn't repeat the work.

1. The hand mishandles transaction IDs

The RH56DFTP firmware has an off-by-one bug in the Modbus TX-ID echo back. Strict clients (pymodbus, etc.) reject the bad IDs as "unexpected response" and eventually close the connection. This package uses a raw socket and deliberately does not validate the TX-ID — it just consumes the response bytes and moves on.

2. Every write must be followed by a synchronous ACK read

The hand always sends a 12-byte ACK after a write. If you don't read it:

  1. Bytes pile up in the hand's TCP send buffer.
  2. Kernel flow control kicks in and blocks the hand's send().
  3. The hand's main loop blocks on that send.
  4. The hand stops responding to new commands, even though your own sendall() keeps reporting success.

Symptom: control feels great for the first few seconds, then the hand freezes — and your client has no idea anything is wrong because writes look fine. Always drain the ACK. We don't need to validate it (see #1); draining it is what matters.

3. Tactile data is big-endian, despite what the manual says

Manual §2.6.20 claims tactile cells are little-endian ("low byte first"). Empirical test on real hardware shows it's big-endian. Little-endian interpretation gives values up to 23000+; big-endian gives the documented 0..4095 range. Likely a doc issue copied from the basic RH56 RS485 protocol (where the data IS little-endian) — the Modbus TCP gateway converts to BE on the wire but the docs weren't updated.

4. The hand needs a brief grace period between TCP reconnects

Closing and immediately reopening a TCP connection sometimes yields a connect that succeeds but then immediately drops. A 300 ms sleep between close() and the next connect() reliably avoids this. Already handled inside InspireHand._reconnect().

Register cheat-sheet (manual §2.6)

Address Block RW Width Notes
1486 ANGLE_SET W 6 regs Target angle, 0..1000 per DOF
1522 SPEED_SET W 6 regs Motor speed, 0..1000 per DOF
1546 ANGLE_ACT R 6 regs Actual angle
1582 FORCE_ACT R 6 regs Gripping force per DOF
3000+ tactile (17 regions) R 1185 regs total See registers.TACTILE_REGIONS

All blocks are contiguous and follow DOF_ORDER = [pinky, ring, middle, index, thumb_bend, thumb_rotation].

Tactile sensor map (manual §2.6.20)

17 regions, 1185 cells total, each cell is one 16-bit register valued 0..4095.

Finger Tip Nail/middle Pad
Index 3×3 12×8 10×8
Middle 3×3 12×8 10×8
Ring 3×3 12×8 10×8
Pinky 3×3 12×8 10×8
Thumb 3×3 12×8 (nail) + 3×3 (middle) 12×8
Palm 8×14

The scheduler reads all 17 regions in 11 batched FC=03 requests (35% fewer round-trips than naïve per-region reads). Modbus FC=03 limits each request to 125 registers — the batching plan in registers.TACTILE_READ_BATCHES respects that bound.

Examples

File What it shows
examples/01_basic_control.py Open/close cycle — minimal InspireHand usage
examples/02_tactile_read.py Bypass scheduler, read one tactile region directly
examples/03_mixed_mode.py Background scheduler doing control + tactile at once

Tested against

  • RH56DFTP, factory firmware, IP 192.168.123.211
  • Python 3.10–3.13 on Linux (Ubuntu 22.04, JetPack 6.2.2 on Jetson Orin Nano)
  • Direct Ethernet cable; static host IP in 192.168.123.0/24

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

inspire_rh56dftp-0.1.0.tar.gz (20.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

inspire_rh56dftp-0.1.0-py3-none-any.whl (19.7 kB view details)

Uploaded Python 3

File details

Details for the file inspire_rh56dftp-0.1.0.tar.gz.

File metadata

  • Download URL: inspire_rh56dftp-0.1.0.tar.gz
  • Upload date:
  • Size: 20.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for inspire_rh56dftp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a6a3bb0c171c3153b17413e1fb00fbd451d9b1067ad046160797558c5456e9ef
MD5 6469e97aee6396382e2c3058c6308de1
BLAKE2b-256 daa338a7e00ac36238e5a70e624bc7c5240e8906721fdb167b6560e38f797183

See more details on using hashes here.

File details

Details for the file inspire_rh56dftp-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for inspire_rh56dftp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 644cce5ac40f9cf39d21a50a36dad8aaec23858465fd9f64aa989c550835902c
MD5 5804bb9d78e7fda30f0ae1ba58881b5e
BLAKE2b-256 06de84ab46eb16aa8ff46635a7b070aed00579ef74b0fcb1a30d5fd4021cec4c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page