urkit 0.2.1__tar.gz → 0.3.0__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.2.1 → urkit-0.3.0}/PKG-INFO +95 -55
  2. {urkit-0.2.1 → urkit-0.3.0}/README.md +94 -54
  3. {urkit-0.2.1 → urkit-0.3.0}/pyproject.toml +1 -1
  4. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/__init__.py +2 -4
  5. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/__main__.py +8 -2
  6. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/cli/points.py +69 -52
  7. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/cli/teach.py +94 -20
  8. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/geometry.py +1 -1
  9. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/gripper/__init__.py +2 -2
  10. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/gripper/presets.py +2 -2
  11. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/motion.py +3 -4
  12. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/points.py +1 -1
  13. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/robot.py +21 -20
  14. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/telemetry.py +16 -17
  15. {urkit-0.2.1 → urkit-0.3.0}/src/urkit.egg-info/PKG-INFO +95 -55
  16. {urkit-0.2.1 → urkit-0.3.0}/tests/test_robot_integration.py +1 -5
  17. {urkit-0.2.1 → urkit-0.3.0}/setup.cfg +0 -0
  18. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/cli/__init__.py +0 -0
  19. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/cli/colors.py +0 -0
  20. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/cli/connection_monitor.py +0 -0
  21. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/config.py +0 -0
  22. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/connection.py +0 -0
  23. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/exceptions.py +0 -0
  24. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/gripper/base.py +0 -0
  25. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/gripper/digital.py +0 -0
  26. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/gripper/robotiq.py +0 -0
  27. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/gripper/robotiq_preamble.py +0 -0
  28. {urkit-0.2.1 → urkit-0.3.0}/src/urkit/io.py +0 -0
  29. {urkit-0.2.1 → urkit-0.3.0}/src/urkit.egg-info/SOURCES.txt +0 -0
  30. {urkit-0.2.1 → urkit-0.3.0}/src/urkit.egg-info/dependency_links.txt +0 -0
  31. {urkit-0.2.1 → urkit-0.3.0}/src/urkit.egg-info/entry_points.txt +0 -0
  32. {urkit-0.2.1 → urkit-0.3.0}/src/urkit.egg-info/requires.txt +0 -0
  33. {urkit-0.2.1 → urkit-0.3.0}/src/urkit.egg-info/top_level.txt +0 -0
  34. {urkit-0.2.1 → urkit-0.3.0}/tests/test_exceptions.py +0 -0
  35. {urkit-0.2.1 → urkit-0.3.0}/tests/test_geometry.py +0 -0
  36. {urkit-0.2.1 → urkit-0.3.0}/tests/test_gripper.py +0 -0
  37. {urkit-0.2.1 → urkit-0.3.0}/tests/test_gripper_factory.py +0 -0
  38. {urkit-0.2.1 → urkit-0.3.0}/tests/test_gripper_presets.py +0 -0
  39. {urkit-0.2.1 → urkit-0.3.0}/tests/test_points.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: urkit
3
- Version: 0.2.1
3
+ Version: 0.3.0
4
4
  Summary: Universal Robots e-Series control toolkit built on ur_rtde
5
5
  Author: URKit Contributors
6
6
  License: MIT
@@ -58,14 +58,19 @@ Built on [`ur_rtde`](https://sdurobotics.gitlab.io/ur_rtde/), it packages the op
58
58
  ## Quick Start
59
59
 
60
60
  ```bash
61
- pip install urkit
61
+ pip install -U urkit
62
62
  ```
63
63
 
64
+ The `-U` (upgrade) flag ensures you always get the latest version — this project is in early development and changes frequently.
65
+
64
66
  Requires Python 3.8+ and a Universal Robots e-Series (UR3e to UR30).
65
67
 
66
68
  ### Robot Setup (one-time)
67
69
 
68
- 1. **Network**: `☰` → `System` → `Network`: set the robot's IP and subnet.
70
+ 1. **Network**: `☰` → `System` → `System` → `Network`. Set a static IP on the robot and a matching one on your PC. Both addresses must share the same first three octets (the network), with a different last octet (the host). For example:
71
+ - **Robot**: `172.31.1.42` / Subnet `255.255.255.0`
72
+ - **PC**: `172.31.1.1` / Netmask `255.255.255.0`
73
+ - Verify with `ping 172.31.1.42`. Connect via direct Ethernet cable or a switch.
69
74
  2. **Remote Control**: `☰` → `System` → `Remote Control`: Enable. Press the remote/local button on the pendant.
70
75
  3. **Security**: `☰` → `Security` → `Services`: enable RTDE and disable EtherNet/IP, PROFINET, or MODBUS if they're claiming RTDE registers. Save and restart.
71
76
 
@@ -76,9 +81,9 @@ That's it. No `.urp` files to run, no extra programs needed.
76
81
  If you have a Robotiq gripper, install the **Robotiq Gripper Control** URCap first: download from [robotiq.com/support](https://robotiq.com/support), copy the `.urcap` to a USB drive, and install via `☰` → `Settings` → `System` → `URCaps`.
77
82
 
78
83
  ```python
79
- from urkit import URRobot, ROBOTIQ_2F_85 # or ROBOTIQ_2F_140, ROBOTIQ_HAND_E, or gripper=none
84
+ from urkit import URRobot, ROBOTIQ_HAND_E # or ROBOTIQ_2F_85, ROBOTIQ_2F_140, or gripper=None
80
85
 
81
- robot = URRobot(ip="172.31.1.200", points="points.db", gripper=ROBOTIQ_2F_85)
86
+ robot = URRobot(ip="172.31.1.42", points="points.db", gripper=ROBOTIQ_HAND_E)
82
87
  robot.gripper.activate()
83
88
 
84
89
  robot.move_to("home")
@@ -90,9 +95,9 @@ robot.gripper.open()
90
95
 
91
96
  The typical workflow:
92
97
 
93
- 1. **Teach points** use the CLI to position the robot and save named waypoints.
94
- 2. **Write code** create a robot, move to points by name, apply offsets, run sequences.
95
- 3. **Iterate** add more points, tweak your code, repeat.
98
+ 1. **Teach points.** Use the CLI to position the robot and save named waypoints.
99
+ 2. **Write code.** Create a robot, move to points by name, apply offsets, run sequences.
100
+ 3. **Iterate.** Add more points, tweak your code, repeat.
96
101
 
97
102
  ---
98
103
 
@@ -105,8 +110,8 @@ URKit provides two CLI tools: **teach** for interactive robot control, and **poi
105
110
  The interactive teach pendant for moving the robot, saving points, and checking telemetry:
106
111
 
107
112
  ```bash
108
- urkit teach 172.31.1.200 # with robot IP
109
- urkit teach # reads IP from config.yaml
113
+ urkit teach 172.31.1.42 # with robot IP
114
+ urkit teach # reads IP from config.yaml
110
115
  ```
111
116
 
112
117
  **Flags:**
@@ -121,25 +126,18 @@ urkit teach # reads IP from config.yaml
121
126
  | `--gripper-close-on-high` | Digital polarity: `true` or `false` |
122
127
  | `--points` | Path to `points.db` file (overrides config) |
123
128
  | `--config` | Path to config file (default: `config.yaml` in project root or CWD) |
129
+ | `-e`, `--expert` | Disable safety speed clamping (full speed for goto/tcp-down) |
124
130
  | `-v`, `--verbose` | Show verbose output (debug connection issues) |
125
131
 
126
132
  ### Points Explorer
127
133
 
128
- Browse saved waypoints with real-time search filtering no robot connection needed:
134
+ Browse saved waypoints with real-time search filtering. No robot connection needed:
129
135
 
130
136
  ```bash
131
137
  urkit points # uses default points.db
132
138
  urkit points test_points.db # use specific database
133
139
  ```
134
140
 
135
- **Features:**
136
- - **Type to search** — real-time substring filtering
137
- - **Fuzzy matching** — type `pk` to find `pick_1` (>60% match)
138
- - **Smart sorting** — exact prefix matches first, then substring, then fuzzy
139
- - **Spatial sorting** — points ordered by proximity to "home" point (XYZ distance)
140
- - **Theme-aware** — automatically adapts colors for light/dark terminals
141
- - **Arrow keys** — scroll · **ESC** — quit
142
-
143
141
  ### Key Map
144
142
 
145
143
  All movement and orientation keys support **hold-to-repeat**.
@@ -217,6 +215,23 @@ All movement and orientation keys support **hold-to-repeat**.
217
215
  </tr>
218
216
  </table>
219
217
 
218
+ ### Safety
219
+
220
+ By default, **Go To** and **TCP Down** movements use a slow velocity (0.125 m/s) so its safer for anyone standing near the robot. The user's speed slider still applies as a global multiplier on top of this.
221
+
222
+ Delta movements (W/S/A/D/Q/E) use step-size-based velocities that scale with the speed slider set by the user.
223
+
224
+ To disable the slow default and use full speed, pass `--expert` or set `expert_mode: true` in your config:
225
+
226
+ ```bash
227
+ urkit teach 172.31.1.42 --expert
228
+ ```
229
+
230
+ ```yaml
231
+ # config.yaml
232
+ expert_mode: true
233
+ ```
234
+
220
235
  ---
221
236
 
222
237
  ## API Reference
@@ -226,14 +241,14 @@ All movement and orientation keys support **hold-to-repeat**.
226
241
  ```python
227
242
  from urkit import URRobot, ROBOTIQ_HAND_E
228
243
 
229
- robot = URRobot(ip="172.31.1.200", points="points.db", gripper=ROBOTIQ_HAND_E)
244
+ robot = URRobot(ip="172.31.1.42", points="points.db", gripper=ROBOTIQ_HAND_E)
230
245
  ```
231
246
 
232
247
  With custom motion defaults:
233
248
 
234
249
  ```python
235
250
  robot = URRobot(
236
- ip="172.31.1.200",
251
+ ip="172.31.1.42",
237
252
  points="points.db",
238
253
  gripper=ROBOTIQ_HAND_E,
239
254
  default_vel=0.5, # m/s
@@ -266,39 +281,41 @@ robot.gripper.open() # fully open (blocking by default)
266
281
  robot.gripper.close() # fully closed, stops on contact
267
282
  robot.gripper.open(wait=False) # non-blocking return
268
283
  robot.gripper.set_position(20) # 20mm open (Robotiq only, 0 = closed)
269
- robot.gripper.set_force(50) # grip force: 0-100
270
- robot.gripper.set_speed(80) # movement speed: 0-100
284
+ robot.gripper.set_force(50) # grip force: 0-100 (Robotiq only)
285
+ robot.gripper.set_speed(80) # movement speed: 0-100 (Robotiq only)
271
286
  ```
272
287
 
273
288
  Override preset values for custom fingers:
274
289
 
275
290
  ```python
276
- robot = URRobot(ip="172.31.1.200", points="points.db", gripper=ROBOTIQ_HAND_E, max_mm=120)
291
+ robot = URRobot(ip="172.31.1.42", points="points.db", gripper=ROBOTIQ_HAND_E, max_mm=120)
277
292
  ```
278
293
 
279
294
  #### Digital I/O Grippers
280
295
 
281
- For suction cups, solenoids, or custom actuators:
296
+ Robotiq grippers use a serial protocol over the robot's RS485 port. If you have a suction cup, solenoid, or any actuator controlled by a single digital output pin, use `DigitalGripperConfig` instead. It just turns that pin on (close) and off (open).
282
297
 
283
298
  ```python
284
299
  from urkit import URRobot, DigitalGripperConfig
285
300
 
286
301
  robot = URRobot(
287
- ip="172.31.1.200",
302
+ ip="172.31.1.42",
288
303
  points="points.db",
289
- gripper=DigitalGripperConfig(pin=3),
304
+ gripper=DigitalGripperConfig(pin=3), # pin 3 goes high = close
290
305
  )
291
306
 
292
- robot.gripper.open() # turn pin off (release)
293
- robot.gripper.close() # turn pin on (grab)
307
+ robot.gripper.open() # turn pin 3 off
308
+ robot.gripper.close() # turn pin 3 on
294
309
  ```
295
310
 
311
+ `set_force()` and `set_speed()` are not available for digital grippers.
312
+
296
313
  ### Points & Motion
297
314
 
298
- The points database is optional create a robot without one and attach later:
315
+ The points database is optional. Create a robot without one and attach later:
299
316
 
300
317
  ```python
301
- robot = URRobot(ip="172.31.1.200")
318
+ robot = URRobot(ip="172.31.1.42")
302
319
  robot.points_db = "points.db"
303
320
  ```
304
321
 
@@ -310,21 +327,24 @@ robot.move_to("pick", linear=False) # joint move
310
327
  robot.move_to("pick", vel=1.0, acc=0.5) # override speed
311
328
  ```
312
329
 
313
- #### Raw Poses
330
+ - **Linear (moveL):** TCP moves in a straight line. Predictable path, slower near complex orientations.
331
+ - **Joint (moveJ):** Each joint moves simultaneously. Faster, but the TCP follows an arc.
314
332
 
315
- ```python
316
- robot.move_to([0.5, 0, 0.3, 0, 0, 0]) # [x, y, z, rx, ry, rz]
317
- ```
333
+ #### Pose Format
334
+
335
+ A pose is `[x, y, z, rx, ry, rz]`: position in meters and orientation as a **rotation vector** (axis-angle in radians). This is not RPY (roll/pitch/yaw). The teach pendant displays RPY in degrees, which is a different representation. Values you see on the pendant won't match `get_tcp_pose()` directly.
318
336
 
319
337
  #### Offsets
320
338
 
339
+ Offsets are 6-element lists `[dx, dy, dz, drx, dry, drz]`:
340
+
321
341
  ```python
322
342
  robot.move_to("pick", offset=[0, 0, 0.05, 0, 0, 0]) # 5cm above pick
323
343
  ```
324
344
 
325
345
  #### Resolve a Pose
326
346
 
327
- Get a pose without moving useful for logging, comparisons, or custom motion:
347
+ Get a pose without moving. Useful for logging, comparisons, or custom motion:
328
348
 
329
349
  ```python
330
350
  pose = robot.get_pose("pick")
@@ -338,11 +358,15 @@ robot.move_to(pose) # move to the resolved pose later
338
358
  from urkit import MoveFrame
339
359
 
340
360
  robot.move_frame = MoveFrame.TOOL # default is BASE
341
- robot.move_to("pick", offset=[0, 0, 0.05]) # 5cm along tool Z
361
+ robot.move_relative([0, 0, 0.05, 0, 0, 0]) # 5cm along tool Z
342
362
  ```
343
363
 
344
- - **BASE** (default): offset relative to robot base
345
- - **TOOL**: offset relative to TCP orientation
364
+ - **BASE** (default): delta relative to robot base
365
+ - **TOOL**: delta relative to TCP orientation
366
+
367
+ #### Points are tool-agnostic
368
+
369
+ Points are stored in the active TCP frame, so they work with any tool. If you swap grippers and set the correct TCP offset, your saved points remain valid.
346
370
 
347
371
  #### Point Management
348
372
 
@@ -359,7 +383,7 @@ robot.import_points("backup.json")
359
383
 
360
384
  ```python
361
385
  robot.move_relative([0, 0.01, 0, 0, 0, 0]) # 1cm along Y
362
- robot.move_relative([0, 0, 0.05], frame=MoveFrame.TOOL)
386
+ robot.move_relative([0, 0, 0.05, 0, 0, 0], frame=MoveFrame.TOOL) # 5cm along tool Z
363
387
  ```
364
388
 
365
389
  #### Sequences with Blending
@@ -372,7 +396,7 @@ robot.move_sequence(["a", "b", "c"], blend_radius=0.02)
372
396
  #### Contact Detection
373
397
 
374
398
  ```python
375
- robot.move_until_contact([0, 0, -0.02, 0, 0, 0]) # Ctrl+C to stop
399
+ robot.move_until_contact([0, 0, -0.02, 0, 0, 0])
376
400
  ```
377
401
 
378
402
  #### Velocity Control
@@ -396,11 +420,12 @@ robot.is_freedrive_active # check state
396
420
  #### Speed Control
397
421
 
398
422
  ```python
399
- robot.speed_stop() # emergency stop
400
- robot.set_speed_slider(0.5) # 50% hardware velocity cap
423
+ robot.speed_stop() # stop velocity-controlled motion (not E-stop)
424
+ robot.set_speed_slider(0.5) # 50% velocity cap
425
+ robot.get_speed_slider() # read current slider (0.0-1.0)
401
426
  ```
402
427
 
403
- The speed slider is a hardware-level multiplier — same as the physical slider on the pendant. It's global, persistent, and affects all motion commands.
428
+ The speed slider controls the pendant's speed multiplier. It's global, persistent, and affects all motion commands.
404
429
 
405
430
  #### Inverse Kinematics
406
431
 
@@ -415,7 +440,6 @@ pose = robot.get_tcp_pose() # [x, y, z, rx, ry, rz]
415
440
  joints = robot.get_joint_positions() # [j0..j5]
416
441
  force = robot.get_tcp_force() # [fx, fy, fz, mx, my, mz]
417
442
  mode = robot.get_robot_mode() # "REMOTE_CONTROL", "SERVOING", etc.
418
- scaling = robot.get_speed_scaling() # 0.0-1.0
419
443
  payload = robot.get_payload() # kg
420
444
  robot.is_protective_stopped() # bool
421
445
  robot.is_emergency_stopped() # bool
@@ -453,11 +477,12 @@ URKit searches for `config.yaml` in this order:
453
477
 
454
478
  | Key | Description | Example |
455
479
  |-----|-------------|---------|
456
- | `robot_ip` | Robot IP address | `192.168.1.100` |
480
+ | `robot_ip` | Robot IP address | `172.31.1.42` |
457
481
  | `points_path` | Path to SQLite points database | `points.db` |
458
482
  | `gripper` | Gripper preset name | `hand-e`, `2f-85`, `2f-140`, `digital` |
459
483
  | `default_vel` | Default linear velocity (m/s) | `0.5` |
460
484
  | `default_acc` | Default linear acceleration (m/s²) | `0.3` |
485
+ | `expert_mode` | Disable safety speed clamping | `false` |
461
486
 
462
487
  ### Gripper Config
463
488
 
@@ -477,17 +502,17 @@ gripper_config:
477
502
 
478
503
  ### CLI Override Precedence
479
504
 
480
- 1. **CLI flags** `urkit teach 172.31.1.200 --gripper none`
481
- 2. **Config file** values from `config.yaml`
482
- 3. **Built-in defaults** `points.db`, no gripper, 0.5 m/s velocity
505
+ 1. **CLI flags.** `urkit teach 172.31.1.42 --gripper none`
506
+ 2. **Config file.** Values from `config.yaml`
507
+ 3. **Built-in defaults.** `points.db`, no gripper, 0.5 m/s velocity
483
508
 
484
509
  ### Saving Config
485
510
 
486
511
  The CLI **never** modifies your config file automatically. Press **Y** inside the teach pendant to save. This way you only save settings you've actually tested.
487
512
 
488
513
  ```bash
489
- urkit teach 172.31.1.200 --gripper hand-e # test, then press Y
490
- urkit teach # next time: reads from config
514
+ urkit teach 172.31.1.42 --gripper hand-e # test, then press Y
515
+ urkit teach # next time: reads from config
491
516
  ```
492
517
 
493
518
  Multiple workcells:
@@ -505,7 +530,7 @@ from urkit import load_config, resolve_config
505
530
  config = load_config() # auto-resolve
506
531
  config = load_config("/path/to/my.yaml") # explicit path
507
532
  path = resolve_config() # returns Path or None
508
- robot = URRobot.from_config({"robot_ip": "172.31.1.200", "gripper": "2f-85"})
533
+ robot = URRobot.from_config({"robot_ip": "172.31.1.42", "gripper": "2f-85"})
509
534
  ```
510
535
 
511
536
  ---
@@ -517,7 +542,6 @@ robot = URRobot.from_config({"robot_ip": "172.31.1.200", "gripper": "2f-85"})
517
542
  URKit doesn't try to wrap everything. Access the raw `ur_rtde` interfaces for advanced features:
518
543
 
519
544
  ```python
520
- robot.rtde_control.moveUntilContact([0, 0, -0.02, 0, 0, 0])
521
545
  robot.rtde_control.forceMode(...)
522
546
  robot.rtde_control.servoJ(...)
523
547
  robot.rtde_receive.getActualCurrent()
@@ -537,10 +561,10 @@ robot.reconnect_rtde() # reconnect after a drop
537
561
  ### Error Handling
538
562
 
539
563
  ```python
540
- from urkit import URKitError, RobotNotInRemoteModeError, RtdeRegisterConflictError
564
+ from urkit import URKitError, MotionError, PointError
541
565
 
542
566
  try:
543
- robot = URRobot(ip="172.31.1.200", points="points.db")
567
+ robot = URRobot(ip="172.31.1.42", points="points.db")
544
568
  except RobotNotInRemoteModeError:
545
569
  print("Enable remote control on the teach pendant!")
546
570
  except RtdeRegisterConflictError:
@@ -548,3 +572,19 @@ except RtdeRegisterConflictError:
548
572
  except URKitError as e:
549
573
  print(f"Error: {e}")
550
574
  ```
575
+
576
+ Common runtime errors:
577
+
578
+ | Exception | When |
579
+ |-----------|------|
580
+ | `MotionError` | Unreachable pose, bad TCP offset, freedrive failure |
581
+ | `PointError` | Point not found, no points database configured |
582
+ | `GripperError` | Gripper activation or communication failure |
583
+ | `URKitIOError` | Invalid pin number, I/O read/write failure |
584
+ | `TelemetryError` | Cannot read pose, joints, force, etc. |
585
+
586
+ When the robot enters protective stop or the RTDE connection drops, motion commands raise `URKitConnectionError` and the program should exit. The CLI handles this automatically.
587
+
588
+ ### Connection Notes
589
+
590
+ The `URRobot` constructor takes a few seconds on first call: it validates the connection, checks remote mode, powers on the robot, releases brakes, and connects RTDE. Subsequent calls are faster if the robot is already running.