urkit 0.3.6__tar.gz → 0.3.7__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.6 → urkit-0.3.7}/PKG-INFO +11 -1
  2. {urkit-0.3.6 → urkit-0.3.7}/README.md +10 -0
  3. {urkit-0.3.6 → urkit-0.3.7}/pyproject.toml +1 -1
  4. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/__init__.py +1 -1
  5. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/cli/teach.py +1 -1
  6. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/motion.py +28 -4
  7. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/robot.py +28 -8
  8. {urkit-0.3.6 → urkit-0.3.7}/src/urkit.egg-info/PKG-INFO +11 -1
  9. {urkit-0.3.6 → urkit-0.3.7}/setup.cfg +0 -0
  10. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/__main__.py +0 -0
  11. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/cli/__init__.py +0 -0
  12. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/cli/colors.py +0 -0
  13. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/cli/connection_monitor.py +0 -0
  14. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/cli/points.py +0 -0
  15. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/config.py +0 -0
  16. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/connection.py +0 -0
  17. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/exceptions.py +0 -0
  18. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/geometry.py +0 -0
  19. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/gripper/__init__.py +0 -0
  20. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/gripper/base.py +0 -0
  21. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/gripper/digital.py +0 -0
  22. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/gripper/presets.py +0 -0
  23. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/gripper/robotiq.py +0 -0
  24. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/gripper/robotiq_preamble.py +0 -0
  25. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/io.py +0 -0
  26. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/points.py +0 -0
  27. {urkit-0.3.6 → urkit-0.3.7}/src/urkit/telemetry.py +0 -0
  28. {urkit-0.3.6 → urkit-0.3.7}/src/urkit.egg-info/SOURCES.txt +0 -0
  29. {urkit-0.3.6 → urkit-0.3.7}/src/urkit.egg-info/dependency_links.txt +0 -0
  30. {urkit-0.3.6 → urkit-0.3.7}/src/urkit.egg-info/entry_points.txt +0 -0
  31. {urkit-0.3.6 → urkit-0.3.7}/src/urkit.egg-info/requires.txt +0 -0
  32. {urkit-0.3.6 → urkit-0.3.7}/src/urkit.egg-info/top_level.txt +0 -0
  33. {urkit-0.3.6 → urkit-0.3.7}/tests/test_exceptions.py +0 -0
  34. {urkit-0.3.6 → urkit-0.3.7}/tests/test_geometry.py +0 -0
  35. {urkit-0.3.6 → urkit-0.3.7}/tests/test_gripper.py +0 -0
  36. {urkit-0.3.6 → urkit-0.3.7}/tests/test_gripper_factory.py +0 -0
  37. {urkit-0.3.6 → urkit-0.3.7}/tests/test_gripper_presets.py +0 -0
  38. {urkit-0.3.6 → urkit-0.3.7}/tests/test_points.py +0 -0
  39. {urkit-0.3.6 → urkit-0.3.7}/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.6
3
+ Version: 0.3.7
4
4
  Summary: Universal Robots e-Series control toolkit built on ur_rtde
5
5
  Author: URKit Contributors
6
6
  License: MIT
@@ -454,7 +454,17 @@ robot.move_sequence(["a", "b", "c"], blend_radius=0.02)
454
454
  #### Contact Detection
455
455
 
456
456
  ```python
457
+ # Zeros FT sensor automatically, then moves until force exceeds threshold
457
458
  robot.move_until_contact([0, 0, -0.02, 0, 0, 0])
459
+
460
+ # Custom threshold (default: 5.0 N/Nm)
461
+ robot.move_until_contact([0, 0, -0.02, 0, 0, 0], threshold=10.0)
462
+
463
+ # Skip zeroing if you need absolute force values
464
+ robot.move_until_contact([0, 0, -0.02, 0, 0, 0], zero_first=False)
465
+
466
+ # Manual zero (e.g. before custom force-based logic)
467
+ robot.zero_ft_sensor()
458
468
  ```
459
469
 
460
470
  #### Velocity Control
@@ -428,7 +428,17 @@ robot.move_sequence(["a", "b", "c"], blend_radius=0.02)
428
428
  #### Contact Detection
429
429
 
430
430
  ```python
431
+ # Zeros FT sensor automatically, then moves until force exceeds threshold
431
432
  robot.move_until_contact([0, 0, -0.02, 0, 0, 0])
433
+
434
+ # Custom threshold (default: 5.0 N/Nm)
435
+ robot.move_until_contact([0, 0, -0.02, 0, 0, 0], threshold=10.0)
436
+
437
+ # Skip zeroing if you need absolute force values
438
+ robot.move_until_contact([0, 0, -0.02, 0, 0, 0], zero_first=False)
439
+
440
+ # Manual zero (e.g. before custom force-based logic)
441
+ robot.zero_ft_sensor()
432
442
  ```
433
443
 
434
444
  #### Velocity Control
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "urkit"
7
- version = "0.3.6"
7
+ version = "0.3.7"
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.6"
27
+ __version__ = "0.3.7"
28
28
 
29
29
  from urkit.config import load_config, resolve_config
30
30
  from urkit.exceptions import (
@@ -1441,7 +1441,7 @@ def teach_command(args) -> None:
1441
1441
  **gripper_kwargs,
1442
1442
  )
1443
1443
  print(" Connected.", flush=True)
1444
- if robot.activate_gripper():
1444
+ if robot._activate_gripper():
1445
1445
  print(" Gripper activated.", flush=True)
1446
1446
  except ConnectionError as e:
1447
1447
  print(f"Connection error: {e}")
@@ -10,7 +10,7 @@ from __future__ import annotations
10
10
  import logging
11
11
  import os
12
12
  import sys
13
- import time as _time
13
+ import time
14
14
  from contextlib import contextmanager
15
15
  from enum import IntEnum
16
16
  from typing import Iterator
@@ -255,12 +255,28 @@ class Motion:
255
255
  f"Relative move failed: {e}"
256
256
  )
257
257
 
258
+ def zero_ft_sensor(self) -> None:
259
+ """Zero the robot's force/torque sensor.
260
+
261
+ Clears the baseline so that subsequent ``getActualTCPForce()``
262
+ readings reflect only forces applied after this call. Call before
263
+ ``move_until_contact()`` or any force-based operation.
264
+
265
+ Raises:
266
+ MotionError: If the command fails.
267
+ """
268
+ try:
269
+ self._rtde_c.zeroFtSensor()
270
+ except Exception as e:
271
+ raise MotionError(f"Failed to zero FT sensor: {e}")
272
+
258
273
  def move_until_contact(
259
274
  self,
260
275
  speed_vector: list[float],
261
276
  *,
262
277
  threshold: float = 5.0,
263
278
  acceleration: float = 0.1,
279
+ zero_first: bool = True,
264
280
  ) -> None:
265
281
  """Move until contact is detected via TCP force sensing.
266
282
 
@@ -280,12 +296,15 @@ class Motion:
280
296
  Contact fires when any of the 6 wrench components changes
281
297
  by more than this value from the baseline reading.
282
298
  acceleration: Acceleration limit passed to ``speedL()`` in m/s².
299
+ zero_first: If True (default), zero the FT sensor before reading
300
+ the baseline. Set to False if you need absolute force values
301
+ rather than delta from zero.
283
302
 
284
303
  Raises:
285
304
  MotionError: If the command fails or the vector is invalid.
286
305
 
287
306
  Example:
288
- >>> # Move straight down until contact
307
+ >>> # Move straight down until contact (zeros FT sensor first)
289
308
  >>> motion.move_until_contact([0, 0, -0.02, 0, 0, 0])
290
309
  >>> # Move down while rotating, higher threshold
291
310
  >>> motion.move_until_contact([0, 0, -0.02, 0, 0.1, 0], threshold=10.0)
@@ -303,6 +322,11 @@ class Motion:
303
322
  speed_vector, threshold,
304
323
  )
305
324
 
325
+ # Zero FT sensor to clear gravity bias before reading baseline
326
+ if zero_first:
327
+ self.zero_ft_sensor()
328
+ time.sleep(0.05) # let sensor settle after zero
329
+
306
330
  # Baseline force reading before the loop
307
331
  baseline = list(self._rtde_r.getActualTCPForce())
308
332
 
@@ -387,9 +411,9 @@ class Motion:
387
411
  raise MotionError(f"Duration must be > 0, got {duration}.")
388
412
 
389
413
  try:
390
- start = _time.monotonic()
414
+ start = time.monotonic()
391
415
  while True:
392
- elapsed = _time.monotonic() - start
416
+ elapsed = time.monotonic() - start
393
417
  if elapsed >= duration:
394
418
  break
395
419
  if not self._rtde_c.isConnected():
@@ -254,19 +254,19 @@ class URRobot:
254
254
 
255
255
  logger.info("URRobot initialized at %s", ip)
256
256
 
257
- def activate_gripper(self, *, timeout: float = 10.0) -> bool:
258
- """Activate the gripper with a timeout.
257
+ def _activate_gripper(self, *, timeout: float = 10.0) -> bool:
258
+ """Activate the gripper with error handling (internal use).
259
259
 
260
260
  Tries to activate the configured gripper. If activation fails
261
261
  or times out (e.g., gripper not physically connected), disconnects
262
262
  the gripper, nulls out ``self._gripper``, and returns ``False``.
263
263
 
264
- This is the single place that handles gripper activation — the
265
- CLI and library code should call this rather than touching
266
- ``gripper.activate()`` directly.
264
+ Users should call ``robot.gripper.activate()`` directly instead.
265
+ This method exists for the CLI which needs graceful fallback
266
+ when the gripper isn't connected.
267
267
 
268
268
  Args:
269
- timeout: Maximum seconds to wait for activation (default 5.0).
269
+ timeout: Maximum seconds to wait for activation (default 10.0).
270
270
 
271
271
  Returns:
272
272
  ``True`` if the gripper was activated successfully,
@@ -1113,16 +1113,31 @@ class URRobot:
1113
1113
  except Exception as e:
1114
1114
  raise MotionError(f"move_sequence failed: {e}")
1115
1115
 
1116
+ def zero_ft_sensor(self) -> None:
1117
+ """Zero the robot's force/torque sensor.
1118
+
1119
+ Clears the baseline so that subsequent force/torque readings
1120
+ reflect only forces applied after this call. Call before
1121
+ ``move_until_contact()`` or any force-based operation.
1122
+
1123
+ Raises:
1124
+ MotionError: If the command fails.
1125
+ """
1126
+ self._check_connection()
1127
+ self._motion.zero_ft_sensor()
1128
+
1116
1129
  def move_until_contact(
1117
1130
  self,
1118
1131
  speed_vector: list[float],
1119
1132
  *,
1120
1133
  threshold: float = 5.0,
1121
1134
  acceleration: float = 0.1,
1135
+ zero_first: bool = True,
1122
1136
  ) -> None:
1123
1137
  """Move until contact is detected via TCP force sensing.
1124
1138
 
1125
1139
  Runs an interruptible control loop — press Ctrl+C to stop at any time.
1140
+ Zeros the FT sensor by default before reading the baseline.
1126
1141
 
1127
1142
  Args:
1128
1143
  speed_vector: 6-element speed vector
@@ -1131,9 +1146,11 @@ class URRobot:
1131
1146
  Contact fires when any wrench component changes by more
1132
1147
  than this value from the baseline reading.
1133
1148
  acceleration: Acceleration limit passed to ``speedL()`` in m/s².
1149
+ zero_first: If True (default), zero the FT sensor before reading
1150
+ the baseline. Set to False if you need absolute force values.
1134
1151
 
1135
1152
  Example:
1136
- >>> # Move straight down until contact
1153
+ >>> # Move straight down until contact (zeros FT sensor first)
1137
1154
  >>> robot.move_until_contact([0, 0, -0.02, 0, 0, 0])
1138
1155
  >>> # Higher threshold for heavier contact
1139
1156
  >>> robot.move_until_contact([0, 0, -0.02, 0, 0, 0], threshold=10.0)
@@ -1141,7 +1158,10 @@ class URRobot:
1141
1158
  self._check_connection()
1142
1159
  self._disable_freedrive_guard()
1143
1160
  self._motion.move_until_contact(
1144
- speed_vector, threshold=threshold, acceleration=acceleration
1161
+ speed_vector,
1162
+ threshold=threshold,
1163
+ acceleration=acceleration,
1164
+ zero_first=zero_first,
1145
1165
  )
1146
1166
 
1147
1167
  def move_velocity(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: urkit
3
- Version: 0.3.6
3
+ Version: 0.3.7
4
4
  Summary: Universal Robots e-Series control toolkit built on ur_rtde
5
5
  Author: URKit Contributors
6
6
  License: MIT
@@ -454,7 +454,17 @@ robot.move_sequence(["a", "b", "c"], blend_radius=0.02)
454
454
  #### Contact Detection
455
455
 
456
456
  ```python
457
+ # Zeros FT sensor automatically, then moves until force exceeds threshold
457
458
  robot.move_until_contact([0, 0, -0.02, 0, 0, 0])
459
+
460
+ # Custom threshold (default: 5.0 N/Nm)
461
+ robot.move_until_contact([0, 0, -0.02, 0, 0, 0], threshold=10.0)
462
+
463
+ # Skip zeroing if you need absolute force values
464
+ robot.move_until_contact([0, 0, -0.02, 0, 0, 0], zero_first=False)
465
+
466
+ # Manual zero (e.g. before custom force-based logic)
467
+ robot.zero_ft_sensor()
458
468
  ```
459
469
 
460
470
  #### Velocity Control
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