urkit 0.3.10__tar.gz → 0.3.12__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 (39) hide show
  1. {urkit-0.3.10 → urkit-0.3.12}/PKG-INFO +1 -1
  2. {urkit-0.3.10 → urkit-0.3.12}/pyproject.toml +1 -1
  3. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/__init__.py +1 -1
  4. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/cli/teach.py +1 -1
  5. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/robot.py +45 -21
  6. {urkit-0.3.10 → urkit-0.3.12}/src/urkit.egg-info/PKG-INFO +1 -1
  7. {urkit-0.3.10 → urkit-0.3.12}/README.md +0 -0
  8. {urkit-0.3.10 → urkit-0.3.12}/setup.cfg +0 -0
  9. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/__main__.py +0 -0
  10. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/cli/__init__.py +0 -0
  11. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/cli/colors.py +0 -0
  12. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/cli/connection_monitor.py +0 -0
  13. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/cli/points.py +0 -0
  14. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/config.py +0 -0
  15. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/connection.py +0 -0
  16. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/exceptions.py +0 -0
  17. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/geometry.py +0 -0
  18. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/gripper/__init__.py +0 -0
  19. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/gripper/base.py +0 -0
  20. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/gripper/digital.py +0 -0
  21. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/gripper/presets.py +0 -0
  22. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/gripper/robotiq.py +0 -0
  23. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/gripper/robotiq_preamble.py +0 -0
  24. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/io.py +0 -0
  25. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/motion.py +0 -0
  26. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/points.py +0 -0
  27. {urkit-0.3.10 → urkit-0.3.12}/src/urkit/telemetry.py +0 -0
  28. {urkit-0.3.10 → urkit-0.3.12}/src/urkit.egg-info/SOURCES.txt +0 -0
  29. {urkit-0.3.10 → urkit-0.3.12}/src/urkit.egg-info/dependency_links.txt +0 -0
  30. {urkit-0.3.10 → urkit-0.3.12}/src/urkit.egg-info/entry_points.txt +0 -0
  31. {urkit-0.3.10 → urkit-0.3.12}/src/urkit.egg-info/requires.txt +0 -0
  32. {urkit-0.3.10 → urkit-0.3.12}/src/urkit.egg-info/top_level.txt +0 -0
  33. {urkit-0.3.10 → urkit-0.3.12}/tests/test_exceptions.py +0 -0
  34. {urkit-0.3.10 → urkit-0.3.12}/tests/test_geometry.py +0 -0
  35. {urkit-0.3.10 → urkit-0.3.12}/tests/test_gripper.py +0 -0
  36. {urkit-0.3.10 → urkit-0.3.12}/tests/test_gripper_factory.py +0 -0
  37. {urkit-0.3.10 → urkit-0.3.12}/tests/test_gripper_presets.py +0 -0
  38. {urkit-0.3.10 → urkit-0.3.12}/tests/test_points.py +0 -0
  39. {urkit-0.3.10 → urkit-0.3.12}/tests/test_robot_integration.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: urkit
3
- Version: 0.3.10
3
+ Version: 0.3.12
4
4
  Summary: Universal Robots e-Series control toolkit built on ur_rtde
5
5
  Author: URKit Contributors
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "urkit"
7
- version = "0.3.10"
7
+ version = "0.3.12"
8
8
  description = "Universal Robots e-Series control toolkit built on ur_rtde"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -24,7 +24,7 @@ Quick start::
24
24
 
25
25
  from __future__ import annotations
26
26
 
27
- __version__ = "0.3.10"
27
+ __version__ = "0.3.12"
28
28
 
29
29
  from urkit.config import load_config, resolve_config
30
30
  from urkit.exceptions import (
@@ -1445,7 +1445,7 @@ def teach_command(args) -> None:
1445
1445
  print(" Gripper activated.", flush=True)
1446
1446
  except ConnectionError as e:
1447
1447
  print(f"Connection error: {e}")
1448
- if "RTDE" in str(e):
1448
+ if "RTDE" in str(e) and "registers are locked" not in str(e):
1449
1449
  print(
1450
1450
  "\n The robot is reachable but RTDE could not connect.\n"
1451
1451
  " This usually means Remote Control is not enabled.\n"
@@ -9,7 +9,7 @@ from __future__ import annotations
9
9
  import logging
10
10
  import sys
11
11
  import time
12
- from typing import TYPE_CHECKING, Union
12
+ from typing import TYPE_CHECKING, Optional, Union
13
13
  from pathlib import Path
14
14
 
15
15
  if TYPE_CHECKING:
@@ -176,21 +176,22 @@ class URRobot:
176
176
  time.sleep(5)
177
177
 
178
178
  # Stop any running program — RTDE cannot upload its control script
179
- # while a program is occupying the Secondary Interface. Only needed
180
- # after a boot (a program left running by another client is their problem).
181
- if boot_needed:
182
- try:
183
- self._stop_program()
184
- time.sleep(2)
185
- except ConnectionError:
186
- logger.warning(
187
- "[URRobot] Could not stop program via Dashboard. "
188
- "Continuing — RTDE connection may fail if a program is running."
189
- )
179
+ # while a program occupies the Secondary Interface. Always try, since
180
+ # a previous session may have left ExternalControl running.
181
+ try:
182
+ self._stop_program()
183
+ time.sleep(2)
184
+ except ConnectionError:
185
+ logger.warning(
186
+ "[URRobot] Could not stop program via Dashboard. "
187
+ "Continuing — RTDE connection may fail if a program is running."
188
+ )
189
+
190
+ # Connect RTDE — retry, the Secondary Interface may need time to
191
+ # release registers after program stop or boot.
192
+ from urkit.exceptions import RtdeRegisterConflictError
190
193
 
191
- # Connect RTDE — retry after boot, the Secondary Interface may need
192
- # extra time to accept connections even after the robot is IDLE.
193
- rtde_attempts = 2 if boot_needed else 1
194
+ rtde_attempts = 2
194
195
  for attempt in range(1, rtde_attempts + 1):
195
196
  try:
196
197
  self._rtde_c, self._rtde_r, self._rtde_io = _connect_rtde(
@@ -198,6 +199,22 @@ class URRobot:
198
199
  frequency=self._rtde_frequency,
199
200
  )
200
201
  break
202
+ except RtdeRegisterConflictError as e:
203
+ if attempt < rtde_attempts:
204
+ logger.warning(
205
+ "[URRobot] RTDE registers in use (attempt %d/%d). "
206
+ "Retrying in 5s...",
207
+ attempt,
208
+ rtde_attempts,
209
+ )
210
+ time.sleep(5)
211
+ else:
212
+ raise ConnectionError(
213
+ f"RTDE registers are locked on robot at {ip}. "
214
+ "A previous session crashed without releasing its connection.\n"
215
+ "Fix: fully shut down the robot controller "
216
+ "(Settings → System → Shutdown), wait 10s, power on."
217
+ ) from e
201
218
  except Exception as e:
202
219
  if attempt < rtde_attempts:
203
220
  logger.warning(
@@ -1474,17 +1491,23 @@ class URRobot:
1474
1491
  # Point management
1475
1492
  # ------------------------------------------------------------------
1476
1493
 
1477
- def save_point(self, name: str) -> Point:
1478
- """Save the current robot position as a named point.
1494
+ def save_point(self, name: str, pose: Optional[list[float]] = None) -> Point:
1495
+ """Save a named point.
1496
+
1497
+ When *pose* is omitted, saves the current TCP pose from
1498
+ getActualTCPPose(). When *pose* is provided, saves that
1499
+ arbitrary pose directly without moving the robot.
1479
1500
 
1480
- Stores the TCP pose from getActualTCPPose(). The UR controller
1481
- interprets the stored pose in whatever TCP frame is active at
1482
- playback time, making points tool-agnostic by design.
1501
+ The UR controller interprets the stored pose in whatever TCP
1502
+ frame is active at playback time, making points tool-agnostic
1503
+ by design.
1483
1504
 
1484
1505
  Overwrites if a point with the same name already exists.
1485
1506
 
1486
1507
  Args:
1487
1508
  name: Name for the saved point.
1509
+ pose: TCP pose [x, y, z, rx, ry, rz]. Defaults to current
1510
+ robot position.
1488
1511
 
1489
1512
  Returns:
1490
1513
  The saved Point object.
@@ -1493,7 +1516,8 @@ class URRobot:
1493
1516
  PointError: If points database is not set or saving fails.
1494
1517
  """
1495
1518
  points = self._require_points()
1496
- pose = self._telemetry.get_tcp_pose()
1519
+ if pose is None:
1520
+ pose = self._telemetry.get_tcp_pose()
1497
1521
  point = Point(name=name, pose=pose)
1498
1522
  points.save(point)
1499
1523
  logger.info("Saved point '%s'", name)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: urkit
3
- Version: 0.3.10
3
+ Version: 0.3.12
4
4
  Summary: Universal Robots e-Series control toolkit built on ur_rtde
5
5
  Author: URKit Contributors
6
6
  License: MIT
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes