urkit 0.4.1__tar.gz → 0.4.3__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.
- {urkit-0.4.1 → urkit-0.4.3}/PKG-INFO +7 -2
- {urkit-0.4.1 → urkit-0.4.3}/README.md +6 -1
- {urkit-0.4.1 → urkit-0.4.3}/pyproject.toml +1 -1
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/__init__.py +1 -1
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/cli/connection_monitor.py +8 -1
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/cli/points.py +44 -41
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/cli/teach.py +191 -208
- urkit-0.4.3/src/urkit/cli/terminal.py +262 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/points.py +8 -5
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/robot.py +7 -6
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit.egg-info/PKG-INFO +7 -2
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit.egg-info/SOURCES.txt +1 -0
- {urkit-0.4.1 → urkit-0.4.3}/setup.cfg +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/__main__.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/cli/__init__.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/cli/colors.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/cli/init.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/config.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/connection.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/exceptions.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/geometry.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/gripper/__init__.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/gripper/base.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/gripper/digital.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/gripper/presets.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/gripper/robotiq.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/gripper/robotiq_preamble.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/io.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/motion.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit/telemetry.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit.egg-info/dependency_links.txt +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit.egg-info/entry_points.txt +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit.egg-info/requires.txt +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/src/urkit.egg-info/top_level.txt +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/tests/test_exceptions.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/tests/test_geometry.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/tests/test_gripper.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/tests/test_gripper_factory.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/tests/test_gripper_presets.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/tests/test_move_sequence.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/tests/test_points.py +0 -0
- {urkit-0.4.1 → urkit-0.4.3}/tests/test_robot_integration.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: urkit
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.3
|
|
4
4
|
Summary: Universal Robots e-Series control toolkit built on ur_rtde
|
|
5
5
|
Author: URKit Contributors
|
|
6
6
|
License: MIT
|
|
@@ -94,6 +94,11 @@ The `-U` (upgrade) flag ensures you always get the latest version. This project
|
|
|
94
94
|
|
|
95
95
|
Requires Python 3.8+ and a Universal Robots e-Series (UR3e to UR30).
|
|
96
96
|
|
|
97
|
+
### Platform Support
|
|
98
|
+
|
|
99
|
+
- **Linux, macOS**: fully supported
|
|
100
|
+
- **Windows**: the Python library works on Windows. The interactive CLIs (`urkit teach`, `urkit points`) run on Windows but are **not fully tested and not officially supported**. A warning is printed at startup. If you hit input or console problems, use Linux, macOS, or WSL2
|
|
101
|
+
|
|
97
102
|
### Robot Setup (one-time)
|
|
98
103
|
|
|
99
104
|
1. **Network**: Connect your PC to the robot via Ethernet cable (direct) or a switch.
|
|
@@ -663,7 +668,7 @@ Default is `None` (controller handles IK natively). Set it globally when most of
|
|
|
663
668
|
|
|
664
669
|
#### Point Management
|
|
665
670
|
|
|
666
|
-
Points are stored in the
|
|
671
|
+
Points are stored as absolute TCP poses in the robot base frame. When you move to a point, the controller moves whatever TCP is currently active to that base-frame pose, so the tool tip lands at the same physical location. Change the TCP offset (or swap grippers) and your saved points stay valid.
|
|
667
672
|
|
|
668
673
|
```python
|
|
669
674
|
robot.save_point("here")
|
|
@@ -68,6 +68,11 @@ The `-U` (upgrade) flag ensures you always get the latest version. This project
|
|
|
68
68
|
|
|
69
69
|
Requires Python 3.8+ and a Universal Robots e-Series (UR3e to UR30).
|
|
70
70
|
|
|
71
|
+
### Platform Support
|
|
72
|
+
|
|
73
|
+
- **Linux, macOS**: fully supported
|
|
74
|
+
- **Windows**: the Python library works on Windows. The interactive CLIs (`urkit teach`, `urkit points`) run on Windows but are **not fully tested and not officially supported**. A warning is printed at startup. If you hit input or console problems, use Linux, macOS, or WSL2
|
|
75
|
+
|
|
71
76
|
### Robot Setup (one-time)
|
|
72
77
|
|
|
73
78
|
1. **Network**: Connect your PC to the robot via Ethernet cable (direct) or a switch.
|
|
@@ -637,7 +642,7 @@ Default is `None` (controller handles IK natively). Set it globally when most of
|
|
|
637
642
|
|
|
638
643
|
#### Point Management
|
|
639
644
|
|
|
640
|
-
Points are stored in the
|
|
645
|
+
Points are stored as absolute TCP poses in the robot base frame. When you move to a point, the controller moves whatever TCP is currently active to that base-frame pose, so the tool tip lands at the same physical location. Change the TCP offset (or swap grippers) and your saved points stay valid.
|
|
641
646
|
|
|
642
647
|
```python
|
|
643
648
|
robot.save_point("here")
|
|
@@ -144,10 +144,17 @@ class ConnectionMonitor:
|
|
|
144
144
|
logger.info("Connection monitor loop exited")
|
|
145
145
|
|
|
146
146
|
def _trigger(self, reason: str) -> None:
|
|
147
|
-
"""Record fault reason and send SIGALRM to interrupt blocking calls.
|
|
147
|
+
"""Record fault reason and send SIGALRM to interrupt blocking calls.
|
|
148
|
+
|
|
149
|
+
On Windows there is no self-signal: the fault_detected flag is
|
|
150
|
+
the only interruption path, and callers poll it between and
|
|
151
|
+
after RTDE calls.
|
|
152
|
+
"""
|
|
148
153
|
self._reason = reason
|
|
149
154
|
self._fault_event.set()
|
|
150
155
|
logger.info("Fault detected: %s", reason)
|
|
156
|
+
if not hasattr(signal, "SIGALRM"):
|
|
157
|
+
return
|
|
151
158
|
try:
|
|
152
159
|
os.kill(os.getpid(), signal.SIGALRM)
|
|
153
160
|
except OSError as e:
|
|
@@ -9,9 +9,7 @@ from __future__ import annotations
|
|
|
9
9
|
|
|
10
10
|
import difflib
|
|
11
11
|
import io
|
|
12
|
-
import select
|
|
13
12
|
import sys
|
|
14
|
-
import termios
|
|
15
13
|
import time
|
|
16
14
|
from pathlib import Path
|
|
17
15
|
|
|
@@ -20,6 +18,7 @@ from rich.table import Table
|
|
|
20
18
|
|
|
21
19
|
from urkit.config import _load_config as load_config
|
|
22
20
|
from urkit.cli.colors import blue, cyan, dim, yellow
|
|
21
|
+
from urkit.cli.terminal import RawTerminal, read_burst, wait_input, warn_if_windows
|
|
23
22
|
from urkit.points import Points
|
|
24
23
|
|
|
25
24
|
|
|
@@ -29,6 +28,7 @@ def points_command(args) -> None:
|
|
|
29
28
|
Args:
|
|
30
29
|
args: Parsed arguments from argparse (with points subcommand attributes).
|
|
31
30
|
"""
|
|
31
|
+
warn_if_windows()
|
|
32
32
|
_explore_points(args)
|
|
33
33
|
|
|
34
34
|
|
|
@@ -120,12 +120,8 @@ def _interactive_points_filter(points_db: Points, all_points: list[str], points_
|
|
|
120
120
|
refresh_error = None
|
|
121
121
|
|
|
122
122
|
# Set terminal to raw mode
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
new_settings[3] = new_settings[3] & ~(termios.ICANON | termios.ECHO)
|
|
126
|
-
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, new_settings)
|
|
127
|
-
|
|
128
|
-
fd = sys.stdin.fileno()
|
|
123
|
+
raw = RawTerminal()
|
|
124
|
+
raw.enable()
|
|
129
125
|
|
|
130
126
|
try:
|
|
131
127
|
while True:
|
|
@@ -238,52 +234,59 @@ def _interactive_points_filter(points_db: Points, all_points: list[str], points_
|
|
|
238
234
|
last_refresh = time.time()
|
|
239
235
|
|
|
240
236
|
# Check for input (non-blocking to allow periodic refresh)
|
|
241
|
-
|
|
242
|
-
if not rlist:
|
|
237
|
+
if not wait_input(0.1):
|
|
243
238
|
continue
|
|
244
239
|
|
|
245
|
-
# Read input
|
|
240
|
+
# Read the full input burst. On Unix an arrow key arrives as
|
|
241
|
+
# \x1b[A in the same burst; on Windows the terminal shim
|
|
242
|
+
# translates arrow keys to the same byte sequence.
|
|
246
243
|
try:
|
|
247
|
-
|
|
244
|
+
text = read_burst(0.0).decode("ascii", errors="replace")
|
|
248
245
|
except Exception:
|
|
249
246
|
break
|
|
247
|
+
if not text:
|
|
248
|
+
continue
|
|
250
249
|
|
|
251
|
-
if
|
|
252
|
-
#
|
|
253
|
-
|
|
254
|
-
if
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
elif ch3 == "B": # Down arrow - scroll down
|
|
264
|
-
filtered = [p for p in all_points_sorted if filter_str == "" or filter_str.lower() in p.lower()]
|
|
265
|
-
scroll = min(len(filtered) - 1, scroll + 1) if filtered else 0
|
|
266
|
-
needs_redraw = True
|
|
267
|
-
except Exception:
|
|
268
|
-
break
|
|
250
|
+
if text.startswith("\x1b"): # ESC or arrow key or function key
|
|
251
|
+
# A bare ESC may still be the first byte of a sequence
|
|
252
|
+
# that arrives late; wait a bit before treating it as quit.
|
|
253
|
+
if text == "\x1b":
|
|
254
|
+
text = text + read_burst(0.2).decode("ascii", errors="replace")
|
|
255
|
+
if "[A" in text: # Up arrow - scroll up
|
|
256
|
+
scroll = max(0, scroll - 1)
|
|
257
|
+
needs_redraw = True
|
|
258
|
+
elif "[B" in text: # Down arrow - scroll down
|
|
259
|
+
filtered = [p for p in all_points_sorted if filter_str == "" or filter_str.lower() in p.lower()]
|
|
260
|
+
scroll = min(len(filtered) - 1, scroll + 1) if filtered else 0
|
|
261
|
+
needs_redraw = True
|
|
269
262
|
else:
|
|
270
|
-
#
|
|
263
|
+
# Just ESC (or an unrecognized sequence) — quit
|
|
264
|
+
break
|
|
265
|
+
else:
|
|
266
|
+
# A burst can mix printable chars and backspaces
|
|
267
|
+
# (fast typing), so process sequentially.
|
|
268
|
+
quit_requested = False
|
|
269
|
+
for ch in text:
|
|
270
|
+
if ch == "\x03": # Ctrl+C (raw byte on Windows)
|
|
271
|
+
quit_requested = True
|
|
272
|
+
break
|
|
273
|
+
elif ch == "\x7f" or ch == "\x08": # Backspace
|
|
274
|
+
if filter_str:
|
|
275
|
+
filter_str = filter_str[:-1]
|
|
276
|
+
scroll = 0
|
|
277
|
+
needs_redraw = True
|
|
278
|
+
elif ch.isprintable():
|
|
279
|
+
filter_str += ch
|
|
280
|
+
scroll = 0
|
|
281
|
+
needs_redraw = True
|
|
282
|
+
if quit_requested:
|
|
271
283
|
break
|
|
272
|
-
elif ch == "\x7f" or ch == "\x08": # Backspace
|
|
273
|
-
if filter_str:
|
|
274
|
-
filter_str = filter_str[:-1]
|
|
275
|
-
scroll = 0
|
|
276
|
-
needs_redraw = True
|
|
277
|
-
elif ch.isprintable():
|
|
278
|
-
filter_str += ch
|
|
279
|
-
scroll = 0
|
|
280
|
-
needs_redraw = True
|
|
281
284
|
|
|
282
285
|
except KeyboardInterrupt:
|
|
283
286
|
# Ctrl+C — exit gracefully without traceback
|
|
284
287
|
pass
|
|
285
288
|
finally:
|
|
286
|
-
|
|
289
|
+
raw.disable()
|
|
287
290
|
sys.stdout.write("\n")
|
|
288
291
|
|
|
289
292
|
|