paxini-sdk 0.1.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.
Files changed (46) hide show
  1. paxini_sdk-0.1.0/LICENSE +21 -0
  2. paxini_sdk-0.1.0/PKG-INFO +234 -0
  3. paxini_sdk-0.1.0/README.md +196 -0
  4. paxini_sdk-0.1.0/paxini_sdk/__init__.py +59 -0
  5. paxini_sdk-0.1.0/paxini_sdk/boards/__init__.py +6 -0
  6. paxini_sdk-0.1.0/paxini_sdk/boards/high_speed.py +414 -0
  7. paxini_sdk-0.1.0/paxini_sdk/boards/serial_converter.py +267 -0
  8. paxini_sdk-0.1.0/paxini_sdk/cli.py +205 -0
  9. paxini_sdk-0.1.0/paxini_sdk/data/pxsr_stdcp03a_points.json +1449 -0
  10. paxini_sdk-0.1.0/paxini_sdk/data/pxsr_stdcp03b_points.json +477 -0
  11. paxini_sdk-0.1.0/paxini_sdk/data/pxsr_stddp03a_points.json +825 -0
  12. paxini_sdk-0.1.0/paxini_sdk/data/pxsr_stddp03b_points.json +777 -0
  13. paxini_sdk-0.1.0/paxini_sdk/data/pxsr_stddp03c_points.json +711 -0
  14. paxini_sdk-0.1.0/paxini_sdk/data/pxsr_stddp03d_points.json +321 -0
  15. paxini_sdk-0.1.0/paxini_sdk/data/pxsr_stddp03e_points.json +591 -0
  16. paxini_sdk-0.1.0/paxini_sdk/data/pxsr_stddp03f_points.json +201 -0
  17. paxini_sdk-0.1.0/paxini_sdk/data/pxsr_stddp03g_points.json +327 -0
  18. paxini_sdk-0.1.0/paxini_sdk/data/pxsr_stdip03a_points.json +423 -0
  19. paxini_sdk-0.1.0/paxini_sdk/data/pxsr_stdip03b_points.json +165 -0
  20. paxini_sdk-0.1.0/paxini_sdk/data/pxsr_stdmc03a_points.json +69 -0
  21. paxini_sdk-0.1.0/paxini_sdk/data/registry.json +125 -0
  22. paxini_sdk-0.1.0/paxini_sdk/exceptions.py +25 -0
  23. paxini_sdk-0.1.0/paxini_sdk/protocol.py +414 -0
  24. paxini_sdk-0.1.0/paxini_sdk/recording.py +223 -0
  25. paxini_sdk-0.1.0/paxini_sdk/registers.py +144 -0
  26. paxini_sdk-0.1.0/paxini_sdk/sensor_registry.py +111 -0
  27. paxini_sdk-0.1.0/paxini_sdk/tools/__init__.py +1 -0
  28. paxini_sdk-0.1.0/paxini_sdk/tools/characterize.py +596 -0
  29. paxini_sdk-0.1.0/paxini_sdk/tools/record.py +110 -0
  30. paxini_sdk-0.1.0/paxini_sdk/tools/smoke_test.py +165 -0
  31. paxini_sdk-0.1.0/paxini_sdk/tools/smoke_test_serial.py +215 -0
  32. paxini_sdk-0.1.0/paxini_sdk/tools/to_rerun.py +398 -0
  33. paxini_sdk-0.1.0/paxini_sdk/transport.py +415 -0
  34. paxini_sdk-0.1.0/paxini_sdk.egg-info/PKG-INFO +234 -0
  35. paxini_sdk-0.1.0/paxini_sdk.egg-info/SOURCES.txt +44 -0
  36. paxini_sdk-0.1.0/paxini_sdk.egg-info/dependency_links.txt +1 -0
  37. paxini_sdk-0.1.0/paxini_sdk.egg-info/entry_points.txt +7 -0
  38. paxini_sdk-0.1.0/paxini_sdk.egg-info/requires.txt +18 -0
  39. paxini_sdk-0.1.0/paxini_sdk.egg-info/top_level.txt +1 -0
  40. paxini_sdk-0.1.0/pyproject.toml +57 -0
  41. paxini_sdk-0.1.0/setup.cfg +4 -0
  42. paxini_sdk-0.1.0/tests/test_auto_push_decoder.py +234 -0
  43. paxini_sdk-0.1.0/tests/test_module_force_decoder.py +84 -0
  44. paxini_sdk-0.1.0/tests/test_protocol.py +138 -0
  45. paxini_sdk-0.1.0/tests/test_recording.py +231 -0
  46. paxini_sdk-0.1.0/tests/test_serial_converter.py +69 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jingyi Zou
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,234 @@
1
+ Metadata-Version: 2.4
2
+ Name: paxini-sdk
3
+ Version: 0.1.0
4
+ Summary: Cross-platform Python SDK + tools for Paxini PX-6AX GEN3 multidimensional tactile sensors.
5
+ Author-email: Jingyi Zou <jingyizou1999@gmail.com>
6
+ License: MIT
7
+ Project-URL: Repository, https://github.com/Jingyi-Z/paxini-sdk
8
+ Project-URL: Issues, https://github.com/Jingyi-Z/paxini-sdk/issues
9
+ Keywords: tactile,robotics,paxini,hall-effect,force-sensor
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: pyserial>=3.5
24
+ Provides-Extra: viz
25
+ Requires-Dist: rerun-sdk>=0.18; extra == "viz"
26
+ Provides-Extra: char
27
+ Requires-Dist: numpy>=1.20; extra == "char"
28
+ Requires-Dist: matplotlib>=3.5; extra == "char"
29
+ Provides-Extra: test
30
+ Requires-Dist: pytest>=7; extra == "test"
31
+ Provides-Extra: dev
32
+ Requires-Dist: pytest>=7; extra == "dev"
33
+ Requires-Dist: rerun-sdk>=0.18; extra == "dev"
34
+ Requires-Dist: openpyxl>=3.1; extra == "dev"
35
+ Requires-Dist: numpy>=1.20; extra == "dev"
36
+ Requires-Dist: matplotlib>=3.5; extra == "dev"
37
+ Dynamic: license-file
38
+
39
+ # paxini-sdk
40
+
41
+ Cross-platform Python SDK and command-line tools for **Paxini PX-6AX GEN3
42
+ multidimensional tactile sensors** — Hall-effect tactile sensors that
43
+ report 3-axis resultant force plus a 9–239-point distributed-force grid
44
+ depending on the variant.
45
+
46
+ Talks to the hardware the vendor's Windows host app supports
47
+ (Serial Converter Board / High-Speed Communication Board), with byte-exact
48
+ protocol match verified against the vendor's reference scripts and
49
+ real-hardware cross-checks.
50
+
51
+ Status: **beta**. Verified on hardware:
52
+
53
+ - High-Speed Communication Board **PXSR-STDOTO4B** (FW02.22) with the
54
+ **DP-S2015-Elite** fingertip (PXSR-STDDP03G, 15 mm, 52 points) — 2026-05-18.
55
+ - Serial Converter Board with the **DP-L3530-Omega** fingertip
56
+ (PXSR-STDDP03A, 30 mm, 135 points) — 2026-05-19.
57
+ - Host OS: Windows 10/11 and macOS (both exercised on hardware).
58
+
59
+ > Disclaimer: this is a community wrapper, not an official Paxini SDK.
60
+ > Force-decoding rules cross-checked against the vendor's `Hand_UI.py` and
61
+ > `USB_UI.py` reference programs; cross-validation against the vendor host
62
+ > app's CSV output is documented in `docs/FINDINGS.md`.
63
+
64
+ ## What ships
65
+
66
+ ```
67
+ paxini_sdk/ Importable package
68
+ protocol.py Frame builders + parsers + LRC + fin error codes
69
+ transport.py pyserial wrapper; length-based frame readers
70
+ registers.py Register addresses, module-name table, bitmap parser
71
+ sensor_registry.py Lookup for 12 GEN3 sensor variants
72
+ recording.py Streaming CSV writer (vendor + native formats)
73
+ boards/
74
+ high_speed.py HighSpeedHandBoard + AutoPushFrame + AutoPushConfig
75
+ serial_converter.py SingleSensorBoard (Serial Converter Board)
76
+ data/ Per-variant (x, y, z) mm coordinate JSONs
77
+ tools/
78
+ smoke_test.py → paxini-smoke console script (high-speed)
79
+ smoke_test_serial.py → paxini-smoke-serial console script (serial board)
80
+ record.py → paxini-record console script
81
+ to_rerun.py → paxini-rerun console script
82
+ characterize.py → paxini-characterize console script
83
+ tests/ 52 offline unit tests (pytest)
84
+ docs/ Usage guide, Windows + Mac setup, full findings log
85
+ ```
86
+
87
+ ## Install
88
+
89
+ ```bash
90
+ # From a clone (recommended while in beta)
91
+ git clone https://github.com/Jingyi-Z/paxini-sdk.git
92
+ cd paxini-sdk
93
+ pip install -e ".[viz]" # viz: also installs rerun-sdk
94
+
95
+ # Or just the core (no visualizer)
96
+ pip install -e .
97
+ ```
98
+
99
+ Python ≥ 3.9. Only hard dependency is `pyserial`; `rerun-sdk` is optional
100
+ for visualization. Use `pip install -e ".[dev]"` for tests + everything.
101
+
102
+ ## Two communication boards
103
+
104
+ The GEN3 sensors connect through one of two vendor boards; the SDK has a
105
+ driver class for each.
106
+
107
+ | Board | Driver class | Protocol | Rate | Sensors |
108
+ | --- | --- | --- | --- | --- |
109
+ | High-Speed Communication Board | `HighSpeedHandBoard` | auto-push stream | ~91 Hz | up to 28 modules; reports each module's point count |
110
+ | Serial Converter Board | `SingleSensorBoard` | request/response | ~176 Hz round-trip (length-based read) | one sensor; **cannot** report its model |
111
+
112
+ The High-Speed board reads the point count from register `0x0030`, so it
113
+ auto-detects the sensor variant. The Serial Converter Board has no such
114
+ register — you must tell `SingleSensorBoard` which sensor is attached
115
+ (`sensor="PXSR-..."` or `n_points=...`), exactly as the vendor `USB_UI.py`
116
+ makes the operator pick the model from a dropdown.
117
+
118
+ ## Quick start
119
+
120
+ Plug the comm board into USB. Make sure the USB-to-UART driver is loaded
121
+ (CH340 on Windows, see `docs/SETUP_WINDOWS.md` / `docs/SETUP_MACOS.md`).
122
+
123
+ ```bash
124
+ # Discover ports
125
+ paxini list
126
+
127
+ # --- High-Speed Communication Board ---
128
+ paxini-smoke --port COM7 --calibrate # Windows
129
+ paxini-smoke --port /dev/cu.usbserial-XXXX --calibrate # macOS
130
+ paxini-rerun --port COM7 --calibrate # 3D rerun viewer
131
+ paxini-record --port COM7 --out runs/session1.csv --calibrate
132
+
133
+ # --- Serial Converter Board (must name the sensor) ---
134
+ paxini-smoke-serial --port COM3 --sensor PXSR-STDDP03A --calibrate
135
+ ```
136
+
137
+ Replay an existing host-app CSV without hardware:
138
+
139
+ ```bash
140
+ paxini-rerun --csv data/2026-05-18-160858.csv
141
+ ```
142
+
143
+ ## Python API
144
+
145
+ High-Speed Communication Board:
146
+
147
+ ```python
148
+ from paxini_sdk import HighSpeedHandBoard
149
+
150
+ with HighSpeedHandBoard("COM7") as hand:
151
+ print("Firmware:", hand.read_version())
152
+ hand.calibrate()
153
+ for frame in hand.stream_auto_push(duration=10.0):
154
+ forces = frame.resultant_forces_newtons
155
+ # {'Index-Tip': (0.2, -0.1, 0.8)} in N
156
+ distributed = frame.distributed_forces_newtons
157
+ # {'Index-Tip': [(0.0, 0.0, 0.4), (0.0, 0.0, 0.5), ...]}
158
+ ```
159
+
160
+ Serial Converter Board (request/response; name the sensor so the
161
+ distributed-force read uses the right length):
162
+
163
+ ```python
164
+ from paxini_sdk import SingleSensorBoard
165
+
166
+ with SingleSensorBoard("COM3", sensor="PXSR-STDDP03A") as board:
167
+ board.calibrate()
168
+ fx, fy, fz = board.read_resultant_force() # raw counts
169
+ points = board.read_distributed_force() # list of DistributedPoint
170
+ # multiply counts by 0.1 for newtons
171
+ ```
172
+
173
+ Force decoding rules (verified against vendor `Hand_UI.py` / `USB_UI.py`):
174
+
175
+ - High-speed module: 6 wire bytes `[Fx_lo Fx_hi Fy_lo Fy_hi Fz_lo Fz_hi]`,
176
+ only low bytes meaningful, Fx/Fy signed int8, Fz uint8.
177
+ - Each distributed-force point: 3 wire bytes `[Fx_lo Fy_lo Fz_lo]`,
178
+ same signed/unsigned rule.
179
+ - Scale: 0.1 N / LSB on every axis.
180
+
181
+ See `docs/USAGE_GUIDE.md` for the full walkthrough and `docs/FINDINGS.md`
182
+ for the protocol-decoding write-up and bugs found during cross-validation.
183
+
184
+ ## Run the tests
185
+
186
+ ```bash
187
+ pip install -e ".[test]"
188
+ pytest -q
189
+ ```
190
+
191
+ Should print `52 passed`. Tests don't need hardware — they verify frame
192
+ builders, parsers, LRC, the payload-aware decoder, and the Serial Converter
193
+ Board point-count handling against synthetic frames and the vendor protocol
194
+ PDF's worked examples.
195
+
196
+ ## Supported hardware
197
+
198
+ | Sensor variant | Vendor part code | Points |
199
+ | --- | --- | --- |
200
+ | MC-M2020-Elite (palm) | PXSR-STDMC03A | 9 |
201
+ | IP-S1610-Elite (finger pad) | PXSR-STDIP03B | 25 |
202
+ | DP-S1813-Elite (13 mm fingertip) | PXSR-STDDP03F | 31 |
203
+ | DP-S1813-Core (13 mm fingertip) | PXSR-STDDP03D | 51 |
204
+ | **DP-S2015-Elite (15 mm fingertip)** | **PXSR-STDDP03G** | **52** |
205
+ | IP-M2324-Core (finger pad) | PXSR-STDIP03A | 68 |
206
+ | CP-M3025-Core (finger pad) | PXSR-STDCP03B | 77 |
207
+ | DP-S3013-Core (integrated tip+pad) | PXSR-STDDP03E | 96 |
208
+ | DP-S2716-Core (16 mm fingertip) | PXSR-STDDP03C | 116 |
209
+ | DP-M2826-Omega (26 mm fingertip) | PXSR-STDDP03B | 127 |
210
+ | **DP-L3530-Omega (30 mm fingertip)** | **PXSR-STDDP03A** | **135** |
211
+ | CP-L5325-Omega (finger pad) | PXSR-STDCP03A | 239 |
212
+
213
+ All 12 variants have distinct point counts, so the High-Speed board's
214
+ reported count resolves the variant unambiguously. The Serial Converter
215
+ Board does not report a point count — pass the part code explicitly.
216
+
217
+ | Comm board | Class | Status |
218
+ | --- | --- | --- |
219
+ | **High-Speed Communication Board** | `HighSpeedHandBoard` | Verified on hardware (2026-05-18) |
220
+ | **Serial Converter Board** | `SingleSensorBoard` | Verified on hardware (2026-05-19) |
221
+ | 10-Channel SPI Hub | Not implemented | Patches welcome |
222
+
223
+ ## License
224
+
225
+ MIT. See `LICENSE`.
226
+
227
+ ## Acknowledgements
228
+
229
+ Built against the vendor's reference scripts shipped in the
230
+ *PaXini PX-6AX GEN3 product package_20251202* (`Hand_UI.py`,
231
+ `Read_Single_Sensor_Hand.py`, `Read_Single_Sensor_Usb.py`, `USB_UI.py`,
232
+ `Read_Single_Sensor_Spi.py`) and the *Communication Board Communication
233
+ Protocol_V1.0.5* PDF. The vendor docs were the source of truth for every
234
+ framing decision; the wrapper code is original.
@@ -0,0 +1,196 @@
1
+ # paxini-sdk
2
+
3
+ Cross-platform Python SDK and command-line tools for **Paxini PX-6AX GEN3
4
+ multidimensional tactile sensors** — Hall-effect tactile sensors that
5
+ report 3-axis resultant force plus a 9–239-point distributed-force grid
6
+ depending on the variant.
7
+
8
+ Talks to the hardware the vendor's Windows host app supports
9
+ (Serial Converter Board / High-Speed Communication Board), with byte-exact
10
+ protocol match verified against the vendor's reference scripts and
11
+ real-hardware cross-checks.
12
+
13
+ Status: **beta**. Verified on hardware:
14
+
15
+ - High-Speed Communication Board **PXSR-STDOTO4B** (FW02.22) with the
16
+ **DP-S2015-Elite** fingertip (PXSR-STDDP03G, 15 mm, 52 points) — 2026-05-18.
17
+ - Serial Converter Board with the **DP-L3530-Omega** fingertip
18
+ (PXSR-STDDP03A, 30 mm, 135 points) — 2026-05-19.
19
+ - Host OS: Windows 10/11 and macOS (both exercised on hardware).
20
+
21
+ > Disclaimer: this is a community wrapper, not an official Paxini SDK.
22
+ > Force-decoding rules cross-checked against the vendor's `Hand_UI.py` and
23
+ > `USB_UI.py` reference programs; cross-validation against the vendor host
24
+ > app's CSV output is documented in `docs/FINDINGS.md`.
25
+
26
+ ## What ships
27
+
28
+ ```
29
+ paxini_sdk/ Importable package
30
+ protocol.py Frame builders + parsers + LRC + fin error codes
31
+ transport.py pyserial wrapper; length-based frame readers
32
+ registers.py Register addresses, module-name table, bitmap parser
33
+ sensor_registry.py Lookup for 12 GEN3 sensor variants
34
+ recording.py Streaming CSV writer (vendor + native formats)
35
+ boards/
36
+ high_speed.py HighSpeedHandBoard + AutoPushFrame + AutoPushConfig
37
+ serial_converter.py SingleSensorBoard (Serial Converter Board)
38
+ data/ Per-variant (x, y, z) mm coordinate JSONs
39
+ tools/
40
+ smoke_test.py → paxini-smoke console script (high-speed)
41
+ smoke_test_serial.py → paxini-smoke-serial console script (serial board)
42
+ record.py → paxini-record console script
43
+ to_rerun.py → paxini-rerun console script
44
+ characterize.py → paxini-characterize console script
45
+ tests/ 52 offline unit tests (pytest)
46
+ docs/ Usage guide, Windows + Mac setup, full findings log
47
+ ```
48
+
49
+ ## Install
50
+
51
+ ```bash
52
+ # From a clone (recommended while in beta)
53
+ git clone https://github.com/Jingyi-Z/paxini-sdk.git
54
+ cd paxini-sdk
55
+ pip install -e ".[viz]" # viz: also installs rerun-sdk
56
+
57
+ # Or just the core (no visualizer)
58
+ pip install -e .
59
+ ```
60
+
61
+ Python ≥ 3.9. Only hard dependency is `pyserial`; `rerun-sdk` is optional
62
+ for visualization. Use `pip install -e ".[dev]"` for tests + everything.
63
+
64
+ ## Two communication boards
65
+
66
+ The GEN3 sensors connect through one of two vendor boards; the SDK has a
67
+ driver class for each.
68
+
69
+ | Board | Driver class | Protocol | Rate | Sensors |
70
+ | --- | --- | --- | --- | --- |
71
+ | High-Speed Communication Board | `HighSpeedHandBoard` | auto-push stream | ~91 Hz | up to 28 modules; reports each module's point count |
72
+ | Serial Converter Board | `SingleSensorBoard` | request/response | ~176 Hz round-trip (length-based read) | one sensor; **cannot** report its model |
73
+
74
+ The High-Speed board reads the point count from register `0x0030`, so it
75
+ auto-detects the sensor variant. The Serial Converter Board has no such
76
+ register — you must tell `SingleSensorBoard` which sensor is attached
77
+ (`sensor="PXSR-..."` or `n_points=...`), exactly as the vendor `USB_UI.py`
78
+ makes the operator pick the model from a dropdown.
79
+
80
+ ## Quick start
81
+
82
+ Plug the comm board into USB. Make sure the USB-to-UART driver is loaded
83
+ (CH340 on Windows, see `docs/SETUP_WINDOWS.md` / `docs/SETUP_MACOS.md`).
84
+
85
+ ```bash
86
+ # Discover ports
87
+ paxini list
88
+
89
+ # --- High-Speed Communication Board ---
90
+ paxini-smoke --port COM7 --calibrate # Windows
91
+ paxini-smoke --port /dev/cu.usbserial-XXXX --calibrate # macOS
92
+ paxini-rerun --port COM7 --calibrate # 3D rerun viewer
93
+ paxini-record --port COM7 --out runs/session1.csv --calibrate
94
+
95
+ # --- Serial Converter Board (must name the sensor) ---
96
+ paxini-smoke-serial --port COM3 --sensor PXSR-STDDP03A --calibrate
97
+ ```
98
+
99
+ Replay an existing host-app CSV without hardware:
100
+
101
+ ```bash
102
+ paxini-rerun --csv data/2026-05-18-160858.csv
103
+ ```
104
+
105
+ ## Python API
106
+
107
+ High-Speed Communication Board:
108
+
109
+ ```python
110
+ from paxini_sdk import HighSpeedHandBoard
111
+
112
+ with HighSpeedHandBoard("COM7") as hand:
113
+ print("Firmware:", hand.read_version())
114
+ hand.calibrate()
115
+ for frame in hand.stream_auto_push(duration=10.0):
116
+ forces = frame.resultant_forces_newtons
117
+ # {'Index-Tip': (0.2, -0.1, 0.8)} in N
118
+ distributed = frame.distributed_forces_newtons
119
+ # {'Index-Tip': [(0.0, 0.0, 0.4), (0.0, 0.0, 0.5), ...]}
120
+ ```
121
+
122
+ Serial Converter Board (request/response; name the sensor so the
123
+ distributed-force read uses the right length):
124
+
125
+ ```python
126
+ from paxini_sdk import SingleSensorBoard
127
+
128
+ with SingleSensorBoard("COM3", sensor="PXSR-STDDP03A") as board:
129
+ board.calibrate()
130
+ fx, fy, fz = board.read_resultant_force() # raw counts
131
+ points = board.read_distributed_force() # list of DistributedPoint
132
+ # multiply counts by 0.1 for newtons
133
+ ```
134
+
135
+ Force decoding rules (verified against vendor `Hand_UI.py` / `USB_UI.py`):
136
+
137
+ - High-speed module: 6 wire bytes `[Fx_lo Fx_hi Fy_lo Fy_hi Fz_lo Fz_hi]`,
138
+ only low bytes meaningful, Fx/Fy signed int8, Fz uint8.
139
+ - Each distributed-force point: 3 wire bytes `[Fx_lo Fy_lo Fz_lo]`,
140
+ same signed/unsigned rule.
141
+ - Scale: 0.1 N / LSB on every axis.
142
+
143
+ See `docs/USAGE_GUIDE.md` for the full walkthrough and `docs/FINDINGS.md`
144
+ for the protocol-decoding write-up and bugs found during cross-validation.
145
+
146
+ ## Run the tests
147
+
148
+ ```bash
149
+ pip install -e ".[test]"
150
+ pytest -q
151
+ ```
152
+
153
+ Should print `52 passed`. Tests don't need hardware — they verify frame
154
+ builders, parsers, LRC, the payload-aware decoder, and the Serial Converter
155
+ Board point-count handling against synthetic frames and the vendor protocol
156
+ PDF's worked examples.
157
+
158
+ ## Supported hardware
159
+
160
+ | Sensor variant | Vendor part code | Points |
161
+ | --- | --- | --- |
162
+ | MC-M2020-Elite (palm) | PXSR-STDMC03A | 9 |
163
+ | IP-S1610-Elite (finger pad) | PXSR-STDIP03B | 25 |
164
+ | DP-S1813-Elite (13 mm fingertip) | PXSR-STDDP03F | 31 |
165
+ | DP-S1813-Core (13 mm fingertip) | PXSR-STDDP03D | 51 |
166
+ | **DP-S2015-Elite (15 mm fingertip)** | **PXSR-STDDP03G** | **52** |
167
+ | IP-M2324-Core (finger pad) | PXSR-STDIP03A | 68 |
168
+ | CP-M3025-Core (finger pad) | PXSR-STDCP03B | 77 |
169
+ | DP-S3013-Core (integrated tip+pad) | PXSR-STDDP03E | 96 |
170
+ | DP-S2716-Core (16 mm fingertip) | PXSR-STDDP03C | 116 |
171
+ | DP-M2826-Omega (26 mm fingertip) | PXSR-STDDP03B | 127 |
172
+ | **DP-L3530-Omega (30 mm fingertip)** | **PXSR-STDDP03A** | **135** |
173
+ | CP-L5325-Omega (finger pad) | PXSR-STDCP03A | 239 |
174
+
175
+ All 12 variants have distinct point counts, so the High-Speed board's
176
+ reported count resolves the variant unambiguously. The Serial Converter
177
+ Board does not report a point count — pass the part code explicitly.
178
+
179
+ | Comm board | Class | Status |
180
+ | --- | --- | --- |
181
+ | **High-Speed Communication Board** | `HighSpeedHandBoard` | Verified on hardware (2026-05-18) |
182
+ | **Serial Converter Board** | `SingleSensorBoard` | Verified on hardware (2026-05-19) |
183
+ | 10-Channel SPI Hub | Not implemented | Patches welcome |
184
+
185
+ ## License
186
+
187
+ MIT. See `LICENSE`.
188
+
189
+ ## Acknowledgements
190
+
191
+ Built against the vendor's reference scripts shipped in the
192
+ *PaXini PX-6AX GEN3 product package_20251202* (`Hand_UI.py`,
193
+ `Read_Single_Sensor_Hand.py`, `Read_Single_Sensor_Usb.py`, `USB_UI.py`,
194
+ `Read_Single_Sensor_Spi.py`) and the *Communication Board Communication
195
+ Protocol_V1.0.5* PDF. The vendor docs were the source of truth for every
196
+ framing decision; the wrapper code is original.
@@ -0,0 +1,59 @@
1
+ """paxini_sdk — cross-platform Python SDK for Paxini PX-6AX GEN3 multidimensional
2
+ tactile sensors.
3
+
4
+ This package wraps the GEN3 communication protocol used by the official
5
+ Paxini USB communication boards (Serial Converter Board and High-Speed
6
+ Communication Board) so that the sensors can be driven on macOS / Linux / Windows
7
+ without the vendor's Windows-only host application.
8
+
9
+ Quick start:
10
+
11
+ from paxini_sdk import list_serial_ports, SingleSensorBoard
12
+
13
+ print(list_serial_ports())
14
+ with SingleSensorBoard("/dev/tty.usbserial-XXXX") as board:
15
+ board.calibrate()
16
+ fx, fy, fz = board.read_resultant_force()
17
+ print(fx, fy, fz)
18
+
19
+ For the high-speed (robotic hand) board:
20
+
21
+ from paxini_sdk import HighSpeedHandBoard
22
+
23
+ with HighSpeedHandBoard("/dev/tty.usbserial-XXXX") as hand:
24
+ print(hand.read_version())
25
+ for frame in hand.stream_auto_push(duration=5.0):
26
+ print(frame.module_forces)
27
+ """
28
+
29
+ from .exceptions import (
30
+ PaxiniError,
31
+ FrameError,
32
+ LRCError,
33
+ DeviceError,
34
+ TimeoutError as PaxiniTimeoutError,
35
+ )
36
+ from .protocol import lrc, build_fin_request, build_simple_request, parse_simple_response
37
+ from .transport import SerialTransport, list_serial_ports
38
+ from .boards.serial_converter import SingleSensorBoard
39
+ from .boards.high_speed import HighSpeedHandBoard, AutoPushFrame
40
+
41
+ __version__ = "0.1.0"
42
+
43
+ __all__ = [
44
+ "PaxiniError",
45
+ "FrameError",
46
+ "LRCError",
47
+ "DeviceError",
48
+ "PaxiniTimeoutError",
49
+ "lrc",
50
+ "build_fin_request",
51
+ "build_simple_request",
52
+ "parse_simple_response",
53
+ "SerialTransport",
54
+ "list_serial_ports",
55
+ "SingleSensorBoard",
56
+ "HighSpeedHandBoard",
57
+ "AutoPushFrame",
58
+ "__version__",
59
+ ]
@@ -0,0 +1,6 @@
1
+ """High-level board classes."""
2
+
3
+ from .serial_converter import SingleSensorBoard
4
+ from .high_speed import HighSpeedHandBoard, AutoPushFrame
5
+
6
+ __all__ = ["SingleSensorBoard", "HighSpeedHandBoard", "AutoPushFrame"]