urkit 0.2.1__tar.gz → 3.1__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.2.1 → urkit-3.1}/PKG-INFO +165 -54
- {urkit-0.2.1 → urkit-3.1}/README.md +164 -53
- {urkit-0.2.1 → urkit-3.1}/pyproject.toml +5 -1
- {urkit-0.2.1 → urkit-3.1}/src/urkit/__init__.py +2 -4
- {urkit-0.2.1 → urkit-3.1}/src/urkit/__main__.py +8 -2
- {urkit-0.2.1 → urkit-3.1}/src/urkit/cli/points.py +51 -55
- {urkit-0.2.1 → urkit-3.1}/src/urkit/cli/teach.py +299 -56
- {urkit-0.2.1 → urkit-3.1}/src/urkit/config.py +1 -1
- {urkit-0.2.1 → urkit-3.1}/src/urkit/geometry.py +6 -6
- {urkit-0.2.1 → urkit-3.1}/src/urkit/gripper/__init__.py +2 -2
- {urkit-0.2.1 → urkit-3.1}/src/urkit/gripper/base.py +12 -23
- {urkit-0.2.1 → urkit-3.1}/src/urkit/gripper/digital.py +1 -1
- {urkit-0.2.1 → urkit-3.1}/src/urkit/gripper/presets.py +2 -2
- {urkit-0.2.1 → urkit-3.1}/src/urkit/gripper/robotiq.py +6 -3
- {urkit-0.2.1 → urkit-3.1}/src/urkit/motion.py +15 -9
- {urkit-0.2.1 → urkit-3.1}/src/urkit/points.py +4 -3
- {urkit-0.2.1 → urkit-3.1}/src/urkit/robot.py +98 -44
- {urkit-0.2.1 → urkit-3.1}/src/urkit/telemetry.py +16 -17
- {urkit-0.2.1 → urkit-3.1}/src/urkit.egg-info/PKG-INFO +165 -54
- {urkit-0.2.1 → urkit-3.1}/tests/test_robot_integration.py +1 -5
- {urkit-0.2.1 → urkit-3.1}/setup.cfg +0 -0
- {urkit-0.2.1 → urkit-3.1}/src/urkit/cli/__init__.py +0 -0
- {urkit-0.2.1 → urkit-3.1}/src/urkit/cli/colors.py +0 -0
- {urkit-0.2.1 → urkit-3.1}/src/urkit/cli/connection_monitor.py +0 -0
- {urkit-0.2.1 → urkit-3.1}/src/urkit/connection.py +0 -0
- {urkit-0.2.1 → urkit-3.1}/src/urkit/exceptions.py +0 -0
- {urkit-0.2.1 → urkit-3.1}/src/urkit/gripper/robotiq_preamble.py +0 -0
- {urkit-0.2.1 → urkit-3.1}/src/urkit/io.py +0 -0
- {urkit-0.2.1 → urkit-3.1}/src/urkit.egg-info/SOURCES.txt +0 -0
- {urkit-0.2.1 → urkit-3.1}/src/urkit.egg-info/dependency_links.txt +0 -0
- {urkit-0.2.1 → urkit-3.1}/src/urkit.egg-info/entry_points.txt +0 -0
- {urkit-0.2.1 → urkit-3.1}/src/urkit.egg-info/requires.txt +0 -0
- {urkit-0.2.1 → urkit-3.1}/src/urkit.egg-info/top_level.txt +0 -0
- {urkit-0.2.1 → urkit-3.1}/tests/test_exceptions.py +0 -0
- {urkit-0.2.1 → urkit-3.1}/tests/test_geometry.py +0 -0
- {urkit-0.2.1 → urkit-3.1}/tests/test_gripper.py +0 -0
- {urkit-0.2.1 → urkit-3.1}/tests/test_gripper_factory.py +0 -0
- {urkit-0.2.1 → urkit-3.1}/tests/test_gripper_presets.py +0 -0
- {urkit-0.2.1 → urkit-3.1}/tests/test_points.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: urkit
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.1
|
|
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
|
|
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,
|
|
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.
|
|
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
|
|
94
|
-
2. **Write code
|
|
95
|
-
3. **Iterate
|
|
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.
|
|
109
|
-
urkit teach
|
|
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
|
|
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**.
|
|
@@ -197,7 +195,7 @@ All movement and orientation keys support **hold-to-repeat**.
|
|
|
197
195
|
<table>
|
|
198
196
|
<tr><th>Key</th><th>Action</th></tr>
|
|
199
197
|
<tr><td><code>B</code></td><td><strong>Save</strong> current position</td></tr>
|
|
200
|
-
<tr><td><code>G</code></td><td>Go to saved point</td></tr>
|
|
198
|
+
<tr><td><code>G</code></td><td>Go to saved point (<code>Space</code> to cancel mid-move, <code>ESC</code> to exit)</td></tr>
|
|
201
199
|
<tr><td><code>H</code></td><td>Delete saved point</td></tr>
|
|
202
200
|
<tr><td><code>P</code></td><td>Open points explorer</td></tr>
|
|
203
201
|
<tr><td><code>R</code></td><td>Rename saved point</td></tr>
|
|
@@ -217,6 +215,52 @@ All movement and orientation keys support **hold-to-repeat**.
|
|
|
217
215
|
</tr>
|
|
218
216
|
</table>
|
|
219
217
|
|
|
218
|
+
### Joint Display
|
|
219
|
+
|
|
220
|
+
The teach pendant shows live joint angles alongside TCP position and orientation:
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
Position X=+0.432 Y=+0.111 Z=+0.227
|
|
224
|
+
Orientation R=+131.3 P=-121.0 Y= +8.0
|
|
225
|
+
Joints J1=+150.0 J2=+020.0 J3=+160.0
|
|
226
|
+
J4=+050.0 J5=-080.0 J6=+157.0
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Joint angles color-code proximity to mechanical limits:
|
|
230
|
+
|
|
231
|
+
- **Yellow**: within 10% of joint range (warning)
|
|
232
|
+
- **Red**: within 5% of joint range (danger)
|
|
233
|
+
|
|
234
|
+
UR e-Series joint limits:
|
|
235
|
+
|
|
236
|
+
| Joint | Range | Notes |
|
|
237
|
+
|-------|-------|-------|
|
|
238
|
+
| J1 (shoulder pan) | ±360° | Full rotation |
|
|
239
|
+
| J2 (shoulder lift) | ±360° | Full rotation |
|
|
240
|
+
| J3 (elbow) | ±180° | Physically restricted — shoulder lift gets in the way |
|
|
241
|
+
| J4 (wrist 1) | ±360° | Full rotation |
|
|
242
|
+
| J5 (wrist 2) | ±360° | Full rotation |
|
|
243
|
+
| J6 (wrist 3) | ±360° | Tool flange unlimited rotation |
|
|
244
|
+
|
|
245
|
+
Thresholds scale with each joint's range, so warning zones feel proportional across all joints.
|
|
246
|
+
|
|
247
|
+
### Safety
|
|
248
|
+
|
|
249
|
+
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.
|
|
250
|
+
|
|
251
|
+
Delta movements (W/S/A/D/Q/E) use step-size-based velocities that scale with the speed slider set by the user.
|
|
252
|
+
|
|
253
|
+
To disable the slow default and use full speed, pass `--expert` or set `expert_mode: true` in your config:
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
urkit teach 172.31.1.42 --expert
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
```yaml
|
|
260
|
+
# config.yaml
|
|
261
|
+
expert_mode: true
|
|
262
|
+
```
|
|
263
|
+
|
|
220
264
|
---
|
|
221
265
|
|
|
222
266
|
## API Reference
|
|
@@ -226,14 +270,14 @@ All movement and orientation keys support **hold-to-repeat**.
|
|
|
226
270
|
```python
|
|
227
271
|
from urkit import URRobot, ROBOTIQ_HAND_E
|
|
228
272
|
|
|
229
|
-
robot = URRobot(ip="172.31.1.
|
|
273
|
+
robot = URRobot(ip="172.31.1.42", points="points.db", gripper=ROBOTIQ_HAND_E)
|
|
230
274
|
```
|
|
231
275
|
|
|
232
276
|
With custom motion defaults:
|
|
233
277
|
|
|
234
278
|
```python
|
|
235
279
|
robot = URRobot(
|
|
236
|
-
ip="172.31.1.
|
|
280
|
+
ip="172.31.1.42",
|
|
237
281
|
points="points.db",
|
|
238
282
|
gripper=ROBOTIQ_HAND_E,
|
|
239
283
|
default_vel=0.5, # m/s
|
|
@@ -266,39 +310,41 @@ robot.gripper.open() # fully open (blocking by default)
|
|
|
266
310
|
robot.gripper.close() # fully closed, stops on contact
|
|
267
311
|
robot.gripper.open(wait=False) # non-blocking return
|
|
268
312
|
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
|
|
313
|
+
robot.gripper.set_force(50) # grip force: 0-100 (Robotiq only)
|
|
314
|
+
robot.gripper.set_speed(80) # movement speed: 0-100 (Robotiq only)
|
|
271
315
|
```
|
|
272
316
|
|
|
273
317
|
Override preset values for custom fingers:
|
|
274
318
|
|
|
275
319
|
```python
|
|
276
|
-
robot = URRobot(ip="172.31.1.
|
|
320
|
+
robot = URRobot(ip="172.31.1.42", points="points.db", gripper=ROBOTIQ_HAND_E, max_mm=120)
|
|
277
321
|
```
|
|
278
322
|
|
|
279
323
|
#### Digital I/O Grippers
|
|
280
324
|
|
|
281
|
-
|
|
325
|
+
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
326
|
|
|
283
327
|
```python
|
|
284
328
|
from urkit import URRobot, DigitalGripperConfig
|
|
285
329
|
|
|
286
330
|
robot = URRobot(
|
|
287
|
-
ip="172.31.1.
|
|
331
|
+
ip="172.31.1.42",
|
|
288
332
|
points="points.db",
|
|
289
|
-
gripper=DigitalGripperConfig(pin=3),
|
|
333
|
+
gripper=DigitalGripperConfig(pin=3), # pin 3 goes high = close
|
|
290
334
|
)
|
|
291
335
|
|
|
292
|
-
robot.gripper.open() # turn pin off
|
|
293
|
-
robot.gripper.close() # turn pin on
|
|
336
|
+
robot.gripper.open() # turn pin 3 off
|
|
337
|
+
robot.gripper.close() # turn pin 3 on
|
|
294
338
|
```
|
|
295
339
|
|
|
340
|
+
`set_force()` and `set_speed()` are not available for digital grippers.
|
|
341
|
+
|
|
296
342
|
### Points & Motion
|
|
297
343
|
|
|
298
|
-
The points database is optional
|
|
344
|
+
The points database is optional. Create a robot without one and attach later:
|
|
299
345
|
|
|
300
346
|
```python
|
|
301
|
-
robot = URRobot(ip="172.31.1.
|
|
347
|
+
robot = URRobot(ip="172.31.1.42")
|
|
302
348
|
robot.points_db = "points.db"
|
|
303
349
|
```
|
|
304
350
|
|
|
@@ -308,23 +354,50 @@ robot.points_db = "points.db"
|
|
|
308
354
|
robot.move_to("pick") # linear move (default)
|
|
309
355
|
robot.move_to("pick", linear=False) # joint move
|
|
310
356
|
robot.move_to("pick", vel=1.0, acc=0.5) # override speed
|
|
357
|
+
robot.move_to("pick", asynchronous=True) # non-blocking, returns immediately
|
|
311
358
|
```
|
|
312
359
|
|
|
313
|
-
|
|
360
|
+
- **Linear (moveL):** TCP moves in a straight line. Predictable path, slower near complex orientations.
|
|
361
|
+
- **Joint (moveJ):** Each joint moves simultaneously. Faster, but the TCP follows an arc.
|
|
362
|
+
- **Asynchronous:** When `asynchronous=True`, the move runs in the UR controller's background thread and the method returns immediately.
|
|
363
|
+
|
|
364
|
+
#### Non-Blocking Moves
|
|
365
|
+
|
|
366
|
+
Start a move and do other things while it runs:
|
|
314
367
|
|
|
315
368
|
```python
|
|
316
|
-
robot.move_to(
|
|
369
|
+
robot.move_to("pick", asynchronous=True)
|
|
370
|
+
|
|
371
|
+
# Poll until done
|
|
372
|
+
while robot.is_moving():
|
|
373
|
+
time.sleep(0.01)
|
|
374
|
+
|
|
375
|
+
# Or cancel mid-move
|
|
376
|
+
robot.move_to("pick", asynchronous=True)
|
|
377
|
+
while robot.is_moving():
|
|
378
|
+
if should_cancel:
|
|
379
|
+
robot.stop() # sends stopL + stopJ
|
|
380
|
+
break
|
|
381
|
+
time.sleep(0.01)
|
|
317
382
|
```
|
|
318
383
|
|
|
384
|
+
**Teach pendant Go To** uses this pattern internally — Space cancels the move and returns to the menu.
|
|
385
|
+
|
|
386
|
+
#### Pose Format
|
|
387
|
+
|
|
388
|
+
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.
|
|
389
|
+
|
|
319
390
|
#### Offsets
|
|
320
391
|
|
|
392
|
+
Offsets are 6-element lists `[dx, dy, dz, drx, dry, drz]`:
|
|
393
|
+
|
|
321
394
|
```python
|
|
322
395
|
robot.move_to("pick", offset=[0, 0, 0.05, 0, 0, 0]) # 5cm above pick
|
|
323
396
|
```
|
|
324
397
|
|
|
325
398
|
#### Resolve a Pose
|
|
326
399
|
|
|
327
|
-
Get a pose without moving
|
|
400
|
+
Get a pose without moving. Useful for logging, comparisons, or custom motion:
|
|
328
401
|
|
|
329
402
|
```python
|
|
330
403
|
pose = robot.get_pose("pick")
|
|
@@ -338,11 +411,15 @@ robot.move_to(pose) # move to the resolved pose later
|
|
|
338
411
|
from urkit import MoveFrame
|
|
339
412
|
|
|
340
413
|
robot.move_frame = MoveFrame.TOOL # default is BASE
|
|
341
|
-
robot.
|
|
414
|
+
robot.move_relative([0, 0, 0.05, 0, 0, 0]) # 5cm along tool Z
|
|
342
415
|
```
|
|
343
416
|
|
|
344
|
-
- **BASE** (default):
|
|
345
|
-
- **TOOL**:
|
|
417
|
+
- **BASE** (default): delta relative to robot base
|
|
418
|
+
- **TOOL**: delta relative to TCP orientation
|
|
419
|
+
|
|
420
|
+
#### Points are tool-agnostic
|
|
421
|
+
|
|
422
|
+
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
423
|
|
|
347
424
|
#### Point Management
|
|
348
425
|
|
|
@@ -359,7 +436,7 @@ robot.import_points("backup.json")
|
|
|
359
436
|
|
|
360
437
|
```python
|
|
361
438
|
robot.move_relative([0, 0.01, 0, 0, 0, 0]) # 1cm along Y
|
|
362
|
-
robot.move_relative([0, 0, 0.05], frame=MoveFrame.TOOL)
|
|
439
|
+
robot.move_relative([0, 0, 0.05, 0, 0, 0], frame=MoveFrame.TOOL) # 5cm along tool Z
|
|
363
440
|
```
|
|
364
441
|
|
|
365
442
|
#### Sequences with Blending
|
|
@@ -372,7 +449,7 @@ robot.move_sequence(["a", "b", "c"], blend_radius=0.02)
|
|
|
372
449
|
#### Contact Detection
|
|
373
450
|
|
|
374
451
|
```python
|
|
375
|
-
robot.move_until_contact([0, 0, -0.02, 0, 0, 0])
|
|
452
|
+
robot.move_until_contact([0, 0, -0.02, 0, 0, 0])
|
|
376
453
|
```
|
|
377
454
|
|
|
378
455
|
#### Velocity Control
|
|
@@ -396,11 +473,13 @@ robot.is_freedrive_active # check state
|
|
|
396
473
|
#### Speed Control
|
|
397
474
|
|
|
398
475
|
```python
|
|
399
|
-
robot.
|
|
400
|
-
robot.
|
|
476
|
+
robot.stop() # stop current move immediately (stopL + stopJ)
|
|
477
|
+
robot.speed_stop() # stop velocity-controlled motion (not E-stop)
|
|
478
|
+
robot.set_speed_slider(0.5) # 50% velocity cap
|
|
479
|
+
robot.get_speed_slider() # read current slider (0.0-1.0)
|
|
401
480
|
```
|
|
402
481
|
|
|
403
|
-
The speed slider
|
|
482
|
+
The speed slider controls the pendant's speed multiplier. It's global, persistent, and affects all motion commands.
|
|
404
483
|
|
|
405
484
|
#### Inverse Kinematics
|
|
406
485
|
|
|
@@ -415,11 +494,27 @@ pose = robot.get_tcp_pose() # [x, y, z, rx, ry, rz]
|
|
|
415
494
|
joints = robot.get_joint_positions() # [j0..j5]
|
|
416
495
|
force = robot.get_tcp_force() # [fx, fy, fz, mx, my, mz]
|
|
417
496
|
mode = robot.get_robot_mode() # "REMOTE_CONTROL", "SERVOING", etc.
|
|
418
|
-
scaling = robot.get_speed_scaling() # 0.0-1.0
|
|
419
497
|
payload = robot.get_payload() # kg
|
|
498
|
+
robot.is_moving() # bool — any joint/TCP velocity non-zero
|
|
420
499
|
robot.is_protective_stopped() # bool
|
|
421
500
|
robot.is_emergency_stopped() # bool
|
|
422
501
|
robot.current_point() # {"pose": [...], "joints": [...]}
|
|
502
|
+
robot.is_at_pose(target) # bool — TCP within 1mm / 0.5°
|
|
503
|
+
robot.is_at_joints(target) # bool — all joints within 0.001 rad
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
`is_moving()` is the simplest way to poll — `is_at_pose()` / `is_at_joints()` for precise target checking:
|
|
507
|
+
|
|
508
|
+
```python
|
|
509
|
+
robot.move_to("pick", asynchronous=True)
|
|
510
|
+
|
|
511
|
+
# Simple: wait until robot stops
|
|
512
|
+
while robot.is_moving():
|
|
513
|
+
time.sleep(0.01)
|
|
514
|
+
|
|
515
|
+
# Precise: check against specific target
|
|
516
|
+
while not robot.is_at_pose(target_pose):
|
|
517
|
+
time.sleep(0.01)
|
|
423
518
|
```
|
|
424
519
|
|
|
425
520
|
### Digital I/O
|
|
@@ -453,11 +548,12 @@ URKit searches for `config.yaml` in this order:
|
|
|
453
548
|
|
|
454
549
|
| Key | Description | Example |
|
|
455
550
|
|-----|-------------|---------|
|
|
456
|
-
| `robot_ip` | Robot IP address | `
|
|
551
|
+
| `robot_ip` | Robot IP address | `172.31.1.42` |
|
|
457
552
|
| `points_path` | Path to SQLite points database | `points.db` |
|
|
458
553
|
| `gripper` | Gripper preset name | `hand-e`, `2f-85`, `2f-140`, `digital` |
|
|
459
554
|
| `default_vel` | Default linear velocity (m/s) | `0.5` |
|
|
460
555
|
| `default_acc` | Default linear acceleration (m/s²) | `0.3` |
|
|
556
|
+
| `expert_mode` | Disable safety speed clamping | `false` |
|
|
461
557
|
|
|
462
558
|
### Gripper Config
|
|
463
559
|
|
|
@@ -477,17 +573,17 @@ gripper_config:
|
|
|
477
573
|
|
|
478
574
|
### CLI Override Precedence
|
|
479
575
|
|
|
480
|
-
1. **CLI flags
|
|
481
|
-
2. **Config file
|
|
482
|
-
3. **Built-in defaults
|
|
576
|
+
1. **CLI flags.** `urkit teach 172.31.1.42 --gripper none`
|
|
577
|
+
2. **Config file.** Values from `config.yaml`
|
|
578
|
+
3. **Built-in defaults.** `points.db`, no gripper, 0.5 m/s velocity
|
|
483
579
|
|
|
484
580
|
### Saving Config
|
|
485
581
|
|
|
486
582
|
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
583
|
|
|
488
584
|
```bash
|
|
489
|
-
urkit teach 172.31.1.
|
|
490
|
-
urkit teach
|
|
585
|
+
urkit teach 172.31.1.42 --gripper hand-e # test, then press Y
|
|
586
|
+
urkit teach # next time: reads from config
|
|
491
587
|
```
|
|
492
588
|
|
|
493
589
|
Multiple workcells:
|
|
@@ -505,7 +601,7 @@ from urkit import load_config, resolve_config
|
|
|
505
601
|
config = load_config() # auto-resolve
|
|
506
602
|
config = load_config("/path/to/my.yaml") # explicit path
|
|
507
603
|
path = resolve_config() # returns Path or None
|
|
508
|
-
robot = URRobot.from_config({"robot_ip": "172.31.1.
|
|
604
|
+
robot = URRobot.from_config({"robot_ip": "172.31.1.42", "gripper": "2f-85"})
|
|
509
605
|
```
|
|
510
606
|
|
|
511
607
|
---
|
|
@@ -517,7 +613,6 @@ robot = URRobot.from_config({"robot_ip": "172.31.1.200", "gripper": "2f-85"})
|
|
|
517
613
|
URKit doesn't try to wrap everything. Access the raw `ur_rtde` interfaces for advanced features:
|
|
518
614
|
|
|
519
615
|
```python
|
|
520
|
-
robot.rtde_control.moveUntilContact([0, 0, -0.02, 0, 0, 0])
|
|
521
616
|
robot.rtde_control.forceMode(...)
|
|
522
617
|
robot.rtde_control.servoJ(...)
|
|
523
618
|
robot.rtde_receive.getActualCurrent()
|
|
@@ -537,10 +632,10 @@ robot.reconnect_rtde() # reconnect after a drop
|
|
|
537
632
|
### Error Handling
|
|
538
633
|
|
|
539
634
|
```python
|
|
540
|
-
from urkit import URKitError,
|
|
635
|
+
from urkit import URKitError, MotionError, PointError
|
|
541
636
|
|
|
542
637
|
try:
|
|
543
|
-
robot = URRobot(ip="172.31.1.
|
|
638
|
+
robot = URRobot(ip="172.31.1.42", points="points.db")
|
|
544
639
|
except RobotNotInRemoteModeError:
|
|
545
640
|
print("Enable remote control on the teach pendant!")
|
|
546
641
|
except RtdeRegisterConflictError:
|
|
@@ -548,3 +643,19 @@ except RtdeRegisterConflictError:
|
|
|
548
643
|
except URKitError as e:
|
|
549
644
|
print(f"Error: {e}")
|
|
550
645
|
```
|
|
646
|
+
|
|
647
|
+
Common runtime errors:
|
|
648
|
+
|
|
649
|
+
| Exception | When |
|
|
650
|
+
|-----------|------|
|
|
651
|
+
| `MotionError` | Unreachable pose, bad TCP offset, freedrive failure |
|
|
652
|
+
| `PointError` | Point not found, no points database configured |
|
|
653
|
+
| `GripperError` | Gripper activation or communication failure |
|
|
654
|
+
| `URKitIOError` | Invalid pin number, I/O read/write failure |
|
|
655
|
+
| `TelemetryError` | Cannot read pose, joints, force, etc. |
|
|
656
|
+
|
|
657
|
+
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.
|
|
658
|
+
|
|
659
|
+
### Connection Notes
|
|
660
|
+
|
|
661
|
+
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.
|