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.
- {urkit-0.3.16 → urkit-0.3.18}/PKG-INFO +1 -1
- {urkit-0.3.16 → urkit-0.3.18}/pyproject.toml +1 -1
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/__init__.py +1 -1
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/cli/teach.py +11 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/config.py +47 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/robot.py +52 -8
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit.egg-info/PKG-INFO +1 -1
- {urkit-0.3.16 → urkit-0.3.18}/README.md +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/setup.cfg +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/__main__.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/cli/__init__.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/cli/colors.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/cli/connection_monitor.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/cli/points.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/connection.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/exceptions.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/geometry.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/gripper/__init__.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/gripper/base.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/gripper/digital.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/gripper/presets.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/gripper/robotiq.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/gripper/robotiq_preamble.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/io.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/motion.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/points.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit/telemetry.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit.egg-info/SOURCES.txt +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit.egg-info/dependency_links.txt +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit.egg-info/entry_points.txt +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit.egg-info/requires.txt +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/src/urkit.egg-info/top_level.txt +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/tests/test_exceptions.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/tests/test_geometry.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/tests/test_gripper.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/tests/test_gripper_factory.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/tests/test_gripper_presets.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/tests/test_points.py +0 -0
- {urkit-0.3.16 → urkit-0.3.18}/tests/test_robot_integration.py +0 -0
|
@@ -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
|
-
|
|
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
|
-
|
|
377
|
-
|
|
378
|
-
|
|
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", "
|
|
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
|
-
|
|
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:
|
|
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
|