urkit 0.3.18__tar.gz → 0.3.19__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.3.18 → urkit-0.3.19}/PKG-INFO +1 -1
- {urkit-0.3.18 → urkit-0.3.19}/pyproject.toml +1 -1
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/__init__.py +1 -1
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/cli/teach.py +13 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/robot.py +76 -11
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit.egg-info/PKG-INFO +1 -1
- {urkit-0.3.18 → urkit-0.3.19}/README.md +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/setup.cfg +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/__main__.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/cli/__init__.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/cli/colors.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/cli/connection_monitor.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/cli/points.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/config.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/connection.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/exceptions.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/geometry.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/gripper/__init__.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/gripper/base.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/gripper/digital.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/gripper/presets.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/gripper/robotiq.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/gripper/robotiq_preamble.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/io.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/motion.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/points.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit/telemetry.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit.egg-info/SOURCES.txt +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit.egg-info/dependency_links.txt +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit.egg-info/entry_points.txt +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit.egg-info/requires.txt +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/src/urkit.egg-info/top_level.txt +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/tests/test_exceptions.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/tests/test_geometry.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/tests/test_gripper.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/tests/test_gripper_factory.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/tests/test_gripper_presets.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/tests/test_points.py +0 -0
- {urkit-0.3.18 → urkit-0.3.19}/tests/test_robot_integration.py +0 -0
|
@@ -738,9 +738,17 @@ def _submenu_goto_point(
|
|
|
738
738
|
time.sleep(0.05)
|
|
739
739
|
|
|
740
740
|
# Show dedicated moving screen with monotonic progress
|
|
741
|
+
# Timeout after 60s in case is_moving() stalls (heavy robot settling,
|
|
742
|
+
# robot already at target, etc.)
|
|
741
743
|
cancelled = False
|
|
744
|
+
timed_out = False
|
|
742
745
|
max_progress = 0.0
|
|
746
|
+
move_start = time.monotonic()
|
|
743
747
|
while robot.is_moving():
|
|
748
|
+
if time.monotonic() - move_start > 60.0:
|
|
749
|
+
timed_out = True
|
|
750
|
+
break
|
|
751
|
+
|
|
744
752
|
pct, bar = _draw_moving_screen(
|
|
745
753
|
robot, name, mode_label, start_pose, target_pose, is_cartesian, max_progress
|
|
746
754
|
)
|
|
@@ -758,6 +766,11 @@ def _submenu_goto_point(
|
|
|
758
766
|
if cancelled:
|
|
759
767
|
robot.stop()
|
|
760
768
|
messages.append(f"Move to '{name}' cancelled")
|
|
769
|
+
elif timed_out:
|
|
770
|
+
messages.append(
|
|
771
|
+
f"Moved to '{name}' ({mode_label}) — "
|
|
772
|
+
"timeout, robot may already have been at target"
|
|
773
|
+
)
|
|
761
774
|
else:
|
|
762
775
|
messages.append(f"Moved to '{name}' ({mode_label})")
|
|
763
776
|
except URKitConnectionError:
|
|
@@ -118,6 +118,10 @@ class URRobot:
|
|
|
118
118
|
self._connection_lost = False
|
|
119
119
|
self._move_frame: MoveFrame = MoveFrame.BASE
|
|
120
120
|
|
|
121
|
+
# Target tracking for pose-based arrival detection in is_moving()
|
|
122
|
+
self._move_target_pose: list[float] | None = None
|
|
123
|
+
self._move_target_joints: list[float] | None = None
|
|
124
|
+
|
|
121
125
|
# Points database (internal) — optional, lazy-initialized
|
|
122
126
|
self._points: Points | None = Points(points) if points is not None else None
|
|
123
127
|
|
|
@@ -1078,6 +1082,14 @@ class URRobot:
|
|
|
1078
1082
|
vel = vel if vel is not None else self._default_vel
|
|
1079
1083
|
acc = acc if acc is not None else self._default_acc
|
|
1080
1084
|
|
|
1085
|
+
# Store target for pose-based arrival detection
|
|
1086
|
+
if linear:
|
|
1087
|
+
self._move_target_pose = list(pose)
|
|
1088
|
+
self._move_target_joints = None
|
|
1089
|
+
else:
|
|
1090
|
+
self._move_target_joints = None # set below after IK
|
|
1091
|
+
self._move_target_pose = list(pose)
|
|
1092
|
+
|
|
1081
1093
|
try:
|
|
1082
1094
|
if linear:
|
|
1083
1095
|
if not self._rtde_c.getInverseKinematicsHasSolution(pose):
|
|
@@ -1085,6 +1097,7 @@ class URRobot:
|
|
|
1085
1097
|
self._motion.movel(pose, vel=vel, acc=acc, asynchronous=asynchronous)
|
|
1086
1098
|
else:
|
|
1087
1099
|
joints = self.inverse_kinematics(pose)
|
|
1100
|
+
self._move_target_joints = list(joints)
|
|
1088
1101
|
self._motion.movej(joints, vel=vel, acc=acc, asynchronous=asynchronous)
|
|
1089
1102
|
except MotionError:
|
|
1090
1103
|
raise
|
|
@@ -1094,13 +1107,29 @@ class URRobot:
|
|
|
1094
1107
|
)
|
|
1095
1108
|
raise MotionError(f"Move to {target_label} failed: {e}")
|
|
1096
1109
|
|
|
1097
|
-
def is_moving(
|
|
1098
|
-
|
|
1110
|
+
def is_moving(
|
|
1111
|
+
self,
|
|
1112
|
+
*,
|
|
1113
|
+
position_tolerance: float = 0.002,
|
|
1114
|
+
orientation_tolerance: float = 0.035,
|
|
1115
|
+
joint_tolerance: float = 0.01,
|
|
1116
|
+
) -> bool:
|
|
1117
|
+
"""Check if the robot has arrived at the last move target.
|
|
1118
|
+
|
|
1119
|
+
Compares current TCP pose (or joint angles for joint moves)
|
|
1120
|
+
to the target stored by ``move_to()``. Returns False when
|
|
1121
|
+
within tolerance.
|
|
1099
1122
|
|
|
1100
|
-
|
|
1123
|
+
Args:
|
|
1124
|
+
position_tolerance: Max distance in meters to consider
|
|
1125
|
+
"arrived" (default 2 mm).
|
|
1126
|
+
orientation_tolerance: Max rotation error in radians to
|
|
1127
|
+
consider "arrived" (default ~2 degrees).
|
|
1128
|
+
joint_tolerance: Max per-joint error in radians for joint
|
|
1129
|
+
moves (default ~0.6 degrees).
|
|
1101
1130
|
|
|
1102
1131
|
Returns:
|
|
1103
|
-
True if moving, False if
|
|
1132
|
+
True if still moving toward target, False if arrived.
|
|
1104
1133
|
|
|
1105
1134
|
Example:
|
|
1106
1135
|
>>> robot.move_to("home", asynchronous=True)
|
|
@@ -1109,15 +1138,38 @@ class URRobot:
|
|
|
1109
1138
|
>>> print("Done!")
|
|
1110
1139
|
"""
|
|
1111
1140
|
try:
|
|
1112
|
-
|
|
1113
|
-
|
|
1141
|
+
# Joint-based: compare current joints to target
|
|
1142
|
+
if self._move_target_joints is not None:
|
|
1143
|
+
current = self._rtde_r.getActualQ()
|
|
1144
|
+
target = self._move_target_joints
|
|
1145
|
+
for c, t in zip(current, target):
|
|
1146
|
+
if abs(c - t) > joint_tolerance:
|
|
1147
|
+
return True
|
|
1148
|
+
self._move_target_joints = None
|
|
1149
|
+
self._move_target_pose = None
|
|
1150
|
+
return False
|
|
1114
1151
|
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1152
|
+
# Pose-based: compare current TCP pose to target
|
|
1153
|
+
if self._move_target_pose is not None:
|
|
1154
|
+
current = self._rtde_r.getActualTCPPose()
|
|
1155
|
+
target = self._move_target_pose
|
|
1156
|
+
dx = current[0] - target[0]
|
|
1157
|
+
dy = current[1] - target[1]
|
|
1158
|
+
dz = current[2] - target[2]
|
|
1159
|
+
dist = (dx * dx + dy * dy + dz * dz) ** 0.5
|
|
1160
|
+
|
|
1161
|
+
d_rx = abs(current[3] - target[3])
|
|
1162
|
+
d_ry = abs(current[4] - target[4])
|
|
1163
|
+
d_rz = abs(current[5] - target[5])
|
|
1164
|
+
orient_err = max(d_rx, d_ry, d_rz)
|
|
1165
|
+
|
|
1166
|
+
if dist <= position_tolerance and orient_err <= orientation_tolerance:
|
|
1167
|
+
self._move_target_pose = None
|
|
1168
|
+
return False
|
|
1169
|
+
return True
|
|
1119
1170
|
|
|
1120
|
-
|
|
1171
|
+
# No target set — assume not moving
|
|
1172
|
+
return False
|
|
1121
1173
|
except Exception:
|
|
1122
1174
|
return False
|
|
1123
1175
|
|
|
@@ -1136,6 +1188,10 @@ class URRobot:
|
|
|
1136
1188
|
self._rtde_c.stopL(5.0, True)
|
|
1137
1189
|
except Exception:
|
|
1138
1190
|
pass
|
|
1191
|
+
|
|
1192
|
+
# Clear move targets so is_moving() falls back to velocity check
|
|
1193
|
+
self._move_target_pose = None
|
|
1194
|
+
self._move_target_joints = None
|
|
1139
1195
|
try:
|
|
1140
1196
|
self._rtde_c.stopJ(5.0, True)
|
|
1141
1197
|
except Exception:
|
|
@@ -1225,10 +1281,19 @@ class URRobot:
|
|
|
1225
1281
|
current = list(self._rtde_r.getActualTCPPose())
|
|
1226
1282
|
target = transform_pose_delta(current, final_delta, effective_frame)
|
|
1227
1283
|
|
|
1284
|
+
# Store target for arrival detection
|
|
1285
|
+
if linear:
|
|
1286
|
+
self._move_target_pose = list(target)
|
|
1287
|
+
self._move_target_joints = None
|
|
1288
|
+
else:
|
|
1289
|
+
self._move_target_pose = list(target)
|
|
1290
|
+
self._move_target_joints = None
|
|
1291
|
+
|
|
1228
1292
|
if linear:
|
|
1229
1293
|
self._motion.movel(target, vel=vel, acc=acc, asynchronous=asynchronous)
|
|
1230
1294
|
else:
|
|
1231
1295
|
joints = self.inverse_kinematics(target)
|
|
1296
|
+
self._move_target_joints = list(joints)
|
|
1232
1297
|
self._motion.movej(joints, vel=vel, acc=acc, asynchronous=asynchronous)
|
|
1233
1298
|
except MotionError:
|
|
1234
1299
|
raise
|
|
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
|
|
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
|