urkit 0.3.16__tar.gz → 0.3.18__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.16 → urkit-0.3.18}/PKG-INFO +1 -1
  2. {urkit-0.3.16 → urkit-0.3.18}/pyproject.toml +1 -1
  3. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/__init__.py +1 -1
  4. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/cli/teach.py +11 -0
  5. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/config.py +47 -0
  6. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/robot.py +52 -8
  7. {urkit-0.3.16 → urkit-0.3.18}/src/urkit.egg-info/PKG-INFO +1 -1
  8. {urkit-0.3.16 → urkit-0.3.18}/README.md +0 -0
  9. {urkit-0.3.16 → urkit-0.3.18}/setup.cfg +0 -0
  10. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/__main__.py +0 -0
  11. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/cli/__init__.py +0 -0
  12. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/cli/colors.py +0 -0
  13. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/cli/connection_monitor.py +0 -0
  14. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/cli/points.py +0 -0
  15. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/connection.py +0 -0
  16. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/exceptions.py +0 -0
  17. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/geometry.py +0 -0
  18. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/gripper/__init__.py +0 -0
  19. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/gripper/base.py +0 -0
  20. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/gripper/digital.py +0 -0
  21. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/gripper/presets.py +0 -0
  22. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/gripper/robotiq.py +0 -0
  23. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/gripper/robotiq_preamble.py +0 -0
  24. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/io.py +0 -0
  25. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/motion.py +0 -0
  26. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/points.py +0 -0
  27. {urkit-0.3.16 → urkit-0.3.18}/src/urkit/telemetry.py +0 -0
  28. {urkit-0.3.16 → urkit-0.3.18}/src/urkit.egg-info/SOURCES.txt +0 -0
  29. {urkit-0.3.16 → urkit-0.3.18}/src/urkit.egg-info/dependency_links.txt +0 -0
  30. {urkit-0.3.16 → urkit-0.3.18}/src/urkit.egg-info/entry_points.txt +0 -0
  31. {urkit-0.3.16 → urkit-0.3.18}/src/urkit.egg-info/requires.txt +0 -0
  32. {urkit-0.3.16 → urkit-0.3.18}/src/urkit.egg-info/top_level.txt +0 -0
  33. {urkit-0.3.16 → urkit-0.3.18}/tests/test_exceptions.py +0 -0
  34. {urkit-0.3.16 → urkit-0.3.18}/tests/test_geometry.py +0 -0
  35. {urkit-0.3.16 → urkit-0.3.18}/tests/test_gripper.py +0 -0
  36. {urkit-0.3.16 → urkit-0.3.18}/tests/test_gripper_factory.py +0 -0
  37. {urkit-0.3.16 → urkit-0.3.18}/tests/test_gripper_presets.py +0 -0
  38. {urkit-0.3.16 → urkit-0.3.18}/tests/test_points.py +0 -0
  39. {urkit-0.3.16 → urkit-0.3.18}/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.16
3
+ Version: 0.3.18
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.16"
7
+ version = "0.3.18"
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.16"
27
+ __version__ = "0.3.18"
28
28
 
29
29
  from urkit.config import load_config, resolve_config
30
30
  from urkit.exceptions import (
@@ -11,6 +11,7 @@ Usage:
11
11
 
12
12
  from __future__ import annotations
13
13
 
14
+ from dataclasses import replace
14
15
  import ipaddress
15
16
  import logging
16
17
  import math
@@ -1395,10 +1396,20 @@ def teach_command(args) -> None:
1395
1396
  gripper_kwargs["close_on_high"] = cfg["close_on_high"] # type: ignore
1396
1397
 
1397
1398
  # Resolve gripper string to config object
1399
+ # Apply physical overrides (tcp_offset, mass, center_of_gravity) from
1400
+ # config.yaml gripper_config section — same as URRobot.from_config()
1401
+ physical_overrides = ("tcp_offset", "mass", "center_of_gravity")
1402
+ physical_kwargs: dict = {}
1403
+ for key in physical_overrides:
1404
+ if key in cfg: # type: ignore
1405
+ physical_kwargs[key] = cfg[key] # type: ignore
1406
+
1398
1407
  gripper_config = None
1399
1408
  if gripper_name:
1400
1409
  preset = PRESETS.get(gripper_name.upper()) # type: ignore
1401
1410
  if preset is not None:
1411
+ if physical_kwargs:
1412
+ preset = replace(preset, **physical_kwargs)
1402
1413
  gripper_config = preset
1403
1414
  elif gripper_name == "digital":
1404
1415
  gripper_config = DigitalGripperConfig( # type: ignore
@@ -14,6 +14,53 @@ Usage::
14
14
  from urkit import URRobot
15
15
  robot = URRobot.from_config("config.yaml")
16
16
  robot = URRobot.from_config("config.yaml", ip="10.0.0.50") # override IP
17
+
18
+ Config YAML format
19
+ ------------------
20
+
21
+ Minimal config::
22
+
23
+ robot_ip: 192.168.1.50
24
+
25
+ Built-in gripper preset (string)::
26
+
27
+ robot_ip: 192.168.1.50
28
+ gripper: hand-e
29
+ gripper_config:
30
+ force: 50
31
+
32
+ Custom gripper with payload + TCP offset (dict)::
33
+
34
+ robot_ip: 192.168.1.50
35
+ gripper:
36
+ mass: 0.5
37
+ center_of_gravity: [0.0, 0.0, 0.0]
38
+ tcp_offset: [0.0, 0.0, 0.175, 0.0, 0.0, 0.0]
39
+ backend: none
40
+
41
+ Override physical properties on a built-in preset::
42
+
43
+ robot_ip: 192.168.1.50
44
+ gripper: hand-e
45
+ gripper_config:
46
+ mass: 1.5
47
+ center_of_gravity: [0.0, 0.0, 0.08]
48
+
49
+ Full config reference::
50
+
51
+ robot_ip: 192.168.1.50 # required
52
+ points_path: points.db # optional, SQLite waypoint DB
53
+ gripper: hand-e # preset name, dict, or omit
54
+ gripper_config: # optional overrides
55
+ mass: 1.0 # kg
56
+ center_of_gravity: [0, 0, 0] # [x, y, z] in meters
57
+ tcp_offset: [0, 0, 0.1, 0, 0, 0] # [x, y, z, rx, ry, rz]
58
+ force: 100 # 0-100
59
+ speed: 100 # 0-100
60
+ max_mm: 50 # finger travel
61
+ default_vel: 0.5 # m/s
62
+ default_acc: 0.3 # m/s²
63
+ expert_mode: false # show advanced CLI commands
17
64
  """
18
65
 
19
66
  from __future__ import annotations
@@ -6,6 +6,7 @@ and named point management into a single high-level interface.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
+ from dataclasses import replace
9
10
  import logging
10
11
  import sys
11
12
  import time
@@ -360,27 +361,36 @@ class URRobot:
360
361
  points: Path to points database. Overrides ``points_path`` from config.
361
362
  gripper: A GripperPreset, DigitalGripperConfig, a preset name
362
363
  string (e.g. ``"hand-e"``, ``"2f-85"``, ``"digital"``),
363
- or ``None``. Overrides the ``gripper`` key from config.
364
+ a dict defining a custom gripper, or ``None``. Overrides
365
+ the ``gripper`` key from config.
364
366
  default_vel: Default linear velocity (m/s).
365
367
  default_acc: Default linear acceleration (m/s²).
366
368
  gripper_kwargs: Overrides for gripper preset values
367
- (e.g. ``max_mm``, ``force``, ``speed``, ``pin``).
369
+ (e.g. ``max_mm``, ``force``, ``speed``, ``pin``,
370
+ ``mass``, ``center_of_gravity``, ``tcp_offset``).
368
371
 
369
372
  Config file keys::
370
373
 
374
+ # Built-in preset (string)
371
375
  robot_ip: 192.168.1.50
372
376
  points_path: points.db
373
377
  gripper: hand-e
374
378
  gripper_config:
379
+ mass: 1.5
375
380
  force: 50
376
- speed: 80
377
- default_vel: 0.5
378
- default_acc: 0.3
381
+
382
+ # Custom gripper (dict) — arbitrary payload + TCP offset
383
+ robot_ip: 192.168.1.50
384
+ gripper:
385
+ mass: 0.5
386
+ center_of_gravity: [0.0, 0.0, 0.0]
387
+ tcp_offset: [0.0, 0.0, 0.175, 0.0, 0.0, 0.0]
388
+ backend: none
379
389
 
380
390
  Example:
381
391
  >>> robot = URRobot.from_config("config.yaml")
382
392
  >>> robot = URRobot.from_config("config.yaml", ip="10.0.0.50")
383
- >>> robot = URRobot.from_config({"robot_ip": "192.168.1.50", "points_path": "points.db", "gripper": "2f-85"})
393
+ >>> robot = URRobot.from_config({"robot_ip": "192.168.1.50", "gripper": {"name": "tool", "mass": 0.5, "center_of_gravity": [0, 0, 0], "tcp_offset": [0, 0, 0.1, 0, 0, 0], "backend": "none"}})
384
394
  """
385
395
  if isinstance(config, str):
386
396
  resolved = resolve_config(config)
@@ -413,6 +423,18 @@ class URRobot:
413
423
  if gripper_source is not None:
414
424
  if isinstance(gripper_source, (GripperPreset, DigitalGripperConfig)):
415
425
  resolved_gripper = gripper_source
426
+ elif isinstance(gripper_source, dict):
427
+ # Custom gripper defined inline in YAML as a dict
428
+ resolved_gripper = GripperPreset(
429
+ name=str(gripper_source.get("name", "custom")),
430
+ mass=float(gripper_source.get("mass", 0.0)),
431
+ center_of_gravity=list(gripper_source.get("center_of_gravity", [0.0, 0.0, 0.0])),
432
+ tcp_offset=list(gripper_source.get("tcp_offset", [0.0, 0.0, 0.0, 0.0, 0.0, 0.0])),
433
+ backend=str(gripper_source.get("backend", "none")),
434
+ max_mm=int(gripper_source.get("max_mm", 50)),
435
+ force=int(gripper_source.get("force", 100)),
436
+ speed=int(gripper_source.get("speed", 100)),
437
+ )
416
438
  elif isinstance(gripper_source, str):
417
439
  key = gripper_source.strip().upper()
418
440
  preset = PRESETS.get(key)
@@ -431,9 +453,31 @@ class URRobot:
431
453
 
432
454
  # Merge config gripper overrides into gripper_kwargs.
433
455
  # Check nested gripper_config first, then top-level for backwards compat.
434
- gripper_overrides = ("max_mm", "force", "speed", "pin", "close_on_high")
435
456
  nested_cfg = cfg.get("gripper_config") or {}
436
- for key in gripper_overrides:
457
+
458
+ # Physical properties override the GripperPreset directly via replace()
459
+ physical_overrides = ("mass", "center_of_gravity", "tcp_offset")
460
+ for key in physical_overrides:
461
+ if key not in gripper_kwargs:
462
+ value = nested_cfg.get(key, cfg.get(key)) # type: ignore
463
+ if value is not None:
464
+ gripper_kwargs[key] = value
465
+
466
+ # Apply physical overrides to the resolved preset
467
+ if isinstance(resolved_gripper, GripperPreset):
468
+ apply_replace: dict[str, object] = {}
469
+ if "mass" in gripper_kwargs:
470
+ apply_replace["mass"] = float(gripper_kwargs.pop("mass"))
471
+ if "center_of_gravity" in gripper_kwargs:
472
+ apply_replace["center_of_gravity"] = list(gripper_kwargs.pop("center_of_gravity"))
473
+ if "tcp_offset" in gripper_kwargs:
474
+ apply_replace["tcp_offset"] = list(gripper_kwargs.pop("tcp_offset"))
475
+ if apply_replace:
476
+ resolved_gripper = replace(resolved_gripper, **apply_replace) # type: ignore[arg-type]
477
+
478
+ # Standard gripper kwargs (passed to Gripper.create)
479
+ standard_overrides = ("max_mm", "force", "speed", "pin", "close_on_high")
480
+ for key in standard_overrides:
437
481
  if key not in gripper_kwargs:
438
482
  value = nested_cfg.get(key, cfg.get(key)) # type: ignore
439
483
  if value is not None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: urkit
3
- Version: 0.3.16
3
+ Version: 0.3.18
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