urkit 0.3.8__tar.gz → 0.3.10__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 (40) hide show
  1. {urkit-0.3.8 → urkit-0.3.10}/PKG-INFO +5 -5
  2. {urkit-0.3.8 → urkit-0.3.10}/pyproject.toml +5 -5
  3. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/__init__.py +1 -1
  4. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/robot.py +68 -17
  5. {urkit-0.3.8 → urkit-0.3.10}/src/urkit.egg-info/PKG-INFO +5 -5
  6. urkit-0.3.10/src/urkit.egg-info/requires.txt +4 -0
  7. urkit-0.3.8/src/urkit.egg-info/requires.txt +0 -4
  8. {urkit-0.3.8 → urkit-0.3.10}/README.md +0 -0
  9. {urkit-0.3.8 → urkit-0.3.10}/setup.cfg +0 -0
  10. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/__main__.py +0 -0
  11. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/cli/__init__.py +0 -0
  12. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/cli/colors.py +0 -0
  13. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/cli/connection_monitor.py +0 -0
  14. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/cli/points.py +0 -0
  15. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/cli/teach.py +0 -0
  16. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/config.py +0 -0
  17. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/connection.py +0 -0
  18. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/exceptions.py +0 -0
  19. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/geometry.py +0 -0
  20. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/gripper/__init__.py +0 -0
  21. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/gripper/base.py +0 -0
  22. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/gripper/digital.py +0 -0
  23. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/gripper/presets.py +0 -0
  24. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/gripper/robotiq.py +0 -0
  25. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/gripper/robotiq_preamble.py +0 -0
  26. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/io.py +0 -0
  27. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/motion.py +0 -0
  28. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/points.py +0 -0
  29. {urkit-0.3.8 → urkit-0.3.10}/src/urkit/telemetry.py +0 -0
  30. {urkit-0.3.8 → urkit-0.3.10}/src/urkit.egg-info/SOURCES.txt +0 -0
  31. {urkit-0.3.8 → urkit-0.3.10}/src/urkit.egg-info/dependency_links.txt +0 -0
  32. {urkit-0.3.8 → urkit-0.3.10}/src/urkit.egg-info/entry_points.txt +0 -0
  33. {urkit-0.3.8 → urkit-0.3.10}/src/urkit.egg-info/top_level.txt +0 -0
  34. {urkit-0.3.8 → urkit-0.3.10}/tests/test_exceptions.py +0 -0
  35. {urkit-0.3.8 → urkit-0.3.10}/tests/test_geometry.py +0 -0
  36. {urkit-0.3.8 → urkit-0.3.10}/tests/test_gripper.py +0 -0
  37. {urkit-0.3.8 → urkit-0.3.10}/tests/test_gripper_factory.py +0 -0
  38. {urkit-0.3.8 → urkit-0.3.10}/tests/test_gripper_presets.py +0 -0
  39. {urkit-0.3.8 → urkit-0.3.10}/tests/test_points.py +0 -0
  40. {urkit-0.3.8 → urkit-0.3.10}/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.8
3
+ Version: 0.3.10
4
4
  Summary: Universal Robots e-Series control toolkit built on ur_rtde
5
5
  Author: URKit Contributors
6
6
  License: MIT
@@ -17,12 +17,12 @@ Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
18
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
19
  Classifier: Topic :: Scientific/Engineering :: Human Machine Interfaces
20
- Requires-Python: >=3.8
20
+ Requires-Python: >=3.10
21
21
  Description-Content-Type: text/markdown
22
- Requires-Dist: ur_rtde>=1.4.0
22
+ Requires-Dist: ur_rtde>=1.6
23
23
  Requires-Dist: pyyaml>=6.0
24
- Requires-Dist: colorama>=0.4.6
25
- Requires-Dist: rich>=13.0.0
24
+ Requires-Dist: colorama>=0.4
25
+ Requires-Dist: rich>=15
26
26
 
27
27
  # URKit
28
28
 
@@ -4,11 +4,11 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "urkit"
7
- version = "0.3.8"
7
+ version = "0.3.10"
8
8
  description = "Universal Robots e-Series control toolkit built on ur_rtde"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
11
- requires-python = ">=3.8"
11
+ requires-python = ">=3.10"
12
12
  authors = [
13
13
  {name = "URKit Contributors"},
14
14
  ]
@@ -44,10 +44,10 @@ classifiers = [
44
44
  "Topic :: Scientific/Engineering :: Human Machine Interfaces",
45
45
  ]
46
46
  dependencies = [
47
- "ur_rtde>=1.4.0",
47
+ "ur_rtde>=1.6",
48
48
  "pyyaml>=6.0",
49
- "colorama>=0.4.6",
50
- "rich>=13.0.0",
49
+ "colorama>=0.4",
50
+ "rich>=15",
51
51
  ]
52
52
 
53
53
  [project.urls]
@@ -24,7 +24,7 @@ Quick start::
24
24
 
25
25
  from __future__ import annotations
26
26
 
27
- __version__ = "0.3.8"
27
+ __version__ = "0.3.10"
28
28
 
29
29
  from urkit.config import load_config, resolve_config
30
30
  from urkit.exceptions import (
@@ -163,7 +163,10 @@ class URRobot:
163
163
  # handles that case too.
164
164
  self._connect_dashboard()
165
165
  did_power_on = self.power_on()
166
- did_release = self.release_brakes()
166
+ # After power_on the robot is IDLE but brakes are still engaged —
167
+ # robotmode can't distinguish "IDLE braked" from "IDLE released",
168
+ # so force the brake release when we just powered on.
169
+ did_release = self.release_brakes(force=did_power_on)
167
170
  boot_needed = did_power_on or did_release
168
171
 
169
172
  # Settle after boot — the robot reports IDLE but the Secondary
@@ -185,11 +188,27 @@ class URRobot:
185
188
  "Continuing — RTDE connection may fail if a program is running."
186
189
  )
187
190
 
188
- # Connect RTDE
189
- self._rtde_c, self._rtde_r, self._rtde_io = _connect_rtde(
190
- ip,
191
- frequency=self._rtde_frequency,
192
- )
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
+ for attempt in range(1, rtde_attempts + 1):
195
+ try:
196
+ self._rtde_c, self._rtde_r, self._rtde_io = _connect_rtde(
197
+ ip,
198
+ frequency=self._rtde_frequency,
199
+ )
200
+ break
201
+ except Exception as e:
202
+ if attempt < rtde_attempts:
203
+ logger.warning(
204
+ "[URRobot] RTDE connection attempt %d failed: %s. "
205
+ "Retrying in 5s...",
206
+ attempt,
207
+ e,
208
+ )
209
+ time.sleep(5)
210
+ else:
211
+ raise
193
212
 
194
213
  # Initialize subsystems
195
214
  self._telemetry = Telemetry(self._rtde_r)
@@ -584,9 +603,13 @@ class URRobot:
584
603
  if "Powering on" in response:
585
604
  _status("Powering on robot...", done=False)
586
605
  logger.info("Robot powering on, waiting for ready state...")
606
+ # Wait until the robot reaches IDLE (brakes engaged, ready for
607
+ # brake release). Stopping at "not POWER_OFF" is insufficient —
608
+ # the robot may still be in POWER_ON or BOOTING where the
609
+ # dashboard rejects "brake release" with a mounting error.
587
610
  self._poll_robotmode(
588
- lambda m: "POWER_OFF" not in m.upper(),
589
- timeout=30.0,
611
+ lambda m: "IDLE" in m.upper(),
612
+ timeout=15.0,
590
613
  )
591
614
  _status("Robot powered on", done=True)
592
615
  return True
@@ -613,11 +636,17 @@ class URRobot:
613
636
  except Exception as e:
614
637
  raise ConnectionError(f"Power off failed: {e}")
615
638
 
616
- def release_brakes(self) -> bool:
639
+ def release_brakes(self, *, force: bool = False) -> bool:
617
640
  """Release the robot brakes (enable control).
618
641
 
619
- Checks the current robot mode first. If the robot is already
620
- in IDLE or RUNNING, the command is skipped silently.
642
+ Checks the current mode first. If the robot is already
643
+ in RUNNING, the command is skipped silently. (IDLE cannot
644
+ distinguish braked from released — use *force* after power_on.)
645
+
646
+ Args:
647
+ force: Skip the mode check and send brake release regardless.
648
+ Should be True when called immediately after power_on(),
649
+ because robotmode reports IDLE for both braked and released.
621
650
 
622
651
  Polls until the robot reports IDLE or RUNNING mode.
623
652
 
@@ -629,20 +658,34 @@ class URRobot:
629
658
  ConnectionError: If brake release fails or times out.
630
659
  """
631
660
  try:
632
- # Check current mode first — skip if already released.
661
+ # Check current mode first — skip if already running.
662
+ # Note: IDLE is ambiguous (brakes may be engaged or released),
663
+ # so we only skip on RUNNING. When force=True (called after
664
+ # power_on), we skip the check entirely.
633
665
  mode = self._send_dashboard("robotmode").upper()
634
- if "IDLE" in mode or "RUNNING" in mode:
666
+ if not force and "RUNNING" in mode:
635
667
  logger.info("Brakes already released (mode: %s), skipping.", mode)
636
668
  return False
637
669
 
638
670
  response = self._send_dashboard("brake release")
639
671
  logger.info("Brake release: %s", response)
672
+
673
+ # Retry once if the mounting calibration wasn't ready.
674
+ if "mounting is not correct" in response:
675
+ logger.info(
676
+ "Brake release rejected (mounting not ready), "
677
+ "retrying after 3s..."
678
+ )
679
+ time.sleep(3)
680
+ response = self._send_dashboard("brake release")
681
+ logger.info("Brake release (retry): %s", response)
682
+
640
683
  if "Brake releasing" in response:
641
684
  _status("Releasing brakes...", done=False)
642
685
  logger.info("Brakes releasing, waiting for ready state...")
643
686
  self._poll_robotmode(
644
687
  lambda m: "IDLE" in m.upper() or "RUNNING" in m.upper(),
645
- timeout=30.0,
688
+ timeout=15.0,
646
689
  )
647
690
  _status("Brakes released", done=True)
648
691
  return True
@@ -916,6 +959,8 @@ class URRobot:
916
959
  current ``move_frame`` property (BASE or TOOL).
917
960
  vel: Velocity override. Falls back to default_vel.
918
961
  acc: Acceleration override. Falls back to default_acc.
962
+ asynchronous: If True, move runs in background and method returns
963
+ immediately (default False).
919
964
  offset_x: X offset in meters (default 0.0).
920
965
  offset_y: Y offset in meters (default 0.0).
921
966
  offset_z: Z offset in meters (default 0.0).
@@ -1039,6 +1084,7 @@ class URRobot:
1039
1084
  frame: MoveFrame | None = None,
1040
1085
  vel: float | None = None,
1041
1086
  acc: float | None = None,
1087
+ asynchronous: bool = False,
1042
1088
  delta_x: float = 0.0,
1043
1089
  delta_y: float = 0.0,
1044
1090
  delta_z: float = 0.0,
@@ -1060,6 +1106,8 @@ class URRobot:
1060
1106
  current ``move_frame`` property (BASE or TOOL).
1061
1107
  vel: Velocity override. Falls back to default_vel.
1062
1108
  acc: Acceleration override. Falls back to default_acc.
1109
+ asynchronous: If True, move runs in background and method returns
1110
+ immediately (default False).
1063
1111
  delta_x: X delta in meters (default 0.0).
1064
1112
  delta_y: Y delta in meters (default 0.0).
1065
1113
  delta_z: Z delta in meters (default 0.0).
@@ -1113,10 +1161,10 @@ class URRobot:
1113
1161
  target = transform_pose_delta(current, final_delta, effective_frame)
1114
1162
 
1115
1163
  if linear:
1116
- self._motion.movel(target, vel=vel, acc=acc)
1164
+ self._motion.movel(target, vel=vel, acc=acc, asynchronous=asynchronous)
1117
1165
  else:
1118
1166
  joints = self.inverse_kinematics(target)
1119
- self._motion.movej(joints, vel=vel, acc=acc)
1167
+ self._motion.movej(joints, vel=vel, acc=acc, asynchronous=asynchronous)
1120
1168
  except MotionError:
1121
1169
  raise
1122
1170
  except Exception as e:
@@ -1130,6 +1178,7 @@ class URRobot:
1130
1178
  blend_radius: float = 0.0,
1131
1179
  vel: float | None = None,
1132
1180
  acc: float | None = None,
1181
+ asynchronous: bool = False,
1133
1182
  ) -> None:
1134
1183
  """Move through a sequence of points with optional blending.
1135
1184
 
@@ -1151,6 +1200,8 @@ class URRobot:
1151
1200
  Applied to intermediate points only.
1152
1201
  vel: Velocity override. Falls back to default_vel.
1153
1202
  acc: Acceleration override. Falls back to default_acc.
1203
+ asynchronous: If True, sequence runs in background and method
1204
+ returns immediately (default False).
1154
1205
 
1155
1206
  Raises:
1156
1207
  MotionError: If the sequence fails or fewer than 2 targets.
@@ -1198,7 +1249,7 @@ class URRobot:
1198
1249
  )
1199
1250
 
1200
1251
  try:
1201
- self._rtde_c.movePath(path, False) # False = synchronous
1252
+ self._rtde_c.movePath(path, not asynchronous)
1202
1253
  except Exception as e:
1203
1254
  raise MotionError(f"move_sequence failed: {e}")
1204
1255
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: urkit
3
- Version: 0.3.8
3
+ Version: 0.3.10
4
4
  Summary: Universal Robots e-Series control toolkit built on ur_rtde
5
5
  Author: URKit Contributors
6
6
  License: MIT
@@ -17,12 +17,12 @@ Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
18
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
19
  Classifier: Topic :: Scientific/Engineering :: Human Machine Interfaces
20
- Requires-Python: >=3.8
20
+ Requires-Python: >=3.10
21
21
  Description-Content-Type: text/markdown
22
- Requires-Dist: ur_rtde>=1.4.0
22
+ Requires-Dist: ur_rtde>=1.6
23
23
  Requires-Dist: pyyaml>=6.0
24
- Requires-Dist: colorama>=0.4.6
25
- Requires-Dist: rich>=13.0.0
24
+ Requires-Dist: colorama>=0.4
25
+ Requires-Dist: rich>=15
26
26
 
27
27
  # URKit
28
28
 
@@ -0,0 +1,4 @@
1
+ ur_rtde>=1.6
2
+ pyyaml>=6.0
3
+ colorama>=0.4
4
+ rich>=15
@@ -1,4 +0,0 @@
1
- ur_rtde>=1.4.0
2
- pyyaml>=6.0
3
- colorama>=0.4.6
4
- rich>=13.0.0
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
File without changes