urkit 0.2.1__tar.gz → 0.3.2__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-0.3.2}/PKG-INFO +186 -54
- {urkit-0.2.1 → urkit-0.3.2}/README.md +185 -53
- {urkit-0.2.1 → urkit-0.3.2}/pyproject.toml +5 -1
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/__init__.py +2 -4
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/__main__.py +8 -2
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/cli/points.py +51 -55
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/cli/teach.py +337 -59
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/config.py +1 -1
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/geometry.py +6 -6
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/gripper/__init__.py +2 -2
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/gripper/base.py +12 -23
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/gripper/digital.py +1 -1
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/gripper/presets.py +2 -2
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/gripper/robotiq.py +9 -3
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/motion.py +15 -9
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/points.py +4 -3
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/robot.py +98 -44
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/telemetry.py +16 -17
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit.egg-info/PKG-INFO +186 -54
- {urkit-0.2.1 → urkit-0.3.2}/tests/test_robot_integration.py +1 -5
- {urkit-0.2.1 → urkit-0.3.2}/setup.cfg +0 -0
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/cli/__init__.py +0 -0
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/cli/colors.py +0 -0
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/cli/connection_monitor.py +0 -0
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/connection.py +0 -0
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/exceptions.py +0 -0
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/gripper/robotiq_preamble.py +0 -0
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit/io.py +0 -0
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit.egg-info/SOURCES.txt +0 -0
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit.egg-info/dependency_links.txt +0 -0
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit.egg-info/entry_points.txt +0 -0
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit.egg-info/requires.txt +0 -0
- {urkit-0.2.1 → urkit-0.3.2}/src/urkit.egg-info/top_level.txt +0 -0
- {urkit-0.2.1 → urkit-0.3.2}/tests/test_exceptions.py +0 -0
- {urkit-0.2.1 → urkit-0.3.2}/tests/test_geometry.py +0 -0
- {urkit-0.2.1 → urkit-0.3.2}/tests/test_gripper.py +0 -0
- {urkit-0.2.1 → urkit-0.3.2}/tests/test_gripper_factory.py +0 -0
- {urkit-0.2.1 → urkit-0.3.2}/tests/test_gripper_presets.py +0 -0
- {urkit-0.2.1 → urkit-0.3.2}/tests/test_points.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: urkit
|
|
3
|
-
Version: 0.2
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: Universal Robots e-Series control toolkit built on ur_rtde
|
|
5
5
|
Author: URKit Contributors
|
|
6
6
|
License: MIT
|
|
@@ -52,20 +52,26 @@ Built on [`ur_rtde`](https://sdurobotics.gitlab.io/ur_rtde/), it packages the op
|
|
|
52
52
|
- [Raw RTDE Access](#raw-rtde-access)
|
|
53
53
|
- [Connection Lifecycle](#connection-lifecycle)
|
|
54
54
|
- [Error Handling](#error-handling)
|
|
55
|
+
- [Changelog](#changelog)
|
|
55
56
|
|
|
56
57
|
---
|
|
57
58
|
|
|
58
59
|
## Quick Start
|
|
59
60
|
|
|
60
61
|
```bash
|
|
61
|
-
pip install urkit
|
|
62
|
+
pip install -U urkit
|
|
62
63
|
```
|
|
63
64
|
|
|
65
|
+
The `-U` (upgrade) flag ensures you always get the latest version — this project is in early development and changes frequently.
|
|
66
|
+
|
|
64
67
|
Requires Python 3.8+ and a Universal Robots e-Series (UR3e to UR30).
|
|
65
68
|
|
|
66
69
|
### Robot Setup (one-time)
|
|
67
70
|
|
|
68
|
-
1. **Network**: `☰` → `System` → `Network
|
|
71
|
+
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:
|
|
72
|
+
- **Robot**: `172.31.1.42` / Subnet `255.255.255.0`
|
|
73
|
+
- **PC**: `172.31.1.1` / Netmask `255.255.255.0`
|
|
74
|
+
- Verify with `ping 172.31.1.42`. Connect via direct Ethernet cable or a switch.
|
|
69
75
|
2. **Remote Control**: `☰` → `System` → `Remote Control`: Enable. Press the remote/local button on the pendant.
|
|
70
76
|
3. **Security**: `☰` → `Security` → `Services`: enable RTDE and disable EtherNet/IP, PROFINET, or MODBUS if they're claiming RTDE registers. Save and restart.
|
|
71
77
|
|
|
@@ -76,9 +82,9 @@ That's it. No `.urp` files to run, no extra programs needed.
|
|
|
76
82
|
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
83
|
|
|
78
84
|
```python
|
|
79
|
-
from urkit import URRobot,
|
|
85
|
+
from urkit import URRobot, ROBOTIQ_HAND_E # or ROBOTIQ_2F_85, ROBOTIQ_2F_140, or gripper=None
|
|
80
86
|
|
|
81
|
-
robot = URRobot(ip="172.31.1.
|
|
87
|
+
robot = URRobot(ip="172.31.1.42", points="points.db", gripper=ROBOTIQ_HAND_E)
|
|
82
88
|
robot.gripper.activate()
|
|
83
89
|
|
|
84
90
|
robot.move_to("home")
|
|
@@ -90,9 +96,9 @@ robot.gripper.open()
|
|
|
90
96
|
|
|
91
97
|
The typical workflow:
|
|
92
98
|
|
|
93
|
-
1. **Teach points
|
|
94
|
-
2. **Write code
|
|
95
|
-
3. **Iterate
|
|
99
|
+
1. **Teach points.** Use the CLI to position the robot and save named waypoints.
|
|
100
|
+
2. **Write code.** Create a robot, move to points by name, apply offsets, run sequences.
|
|
101
|
+
3. **Iterate.** Add more points, tweak your code, repeat.
|
|
96
102
|
|
|
97
103
|
---
|
|
98
104
|
|
|
@@ -105,8 +111,8 @@ URKit provides two CLI tools: **teach** for interactive robot control, and **poi
|
|
|
105
111
|
The interactive teach pendant for moving the robot, saving points, and checking telemetry:
|
|
106
112
|
|
|
107
113
|
```bash
|
|
108
|
-
urkit teach 172.31.1.
|
|
109
|
-
urkit teach
|
|
114
|
+
urkit teach 172.31.1.42 # with robot IP
|
|
115
|
+
urkit teach # reads IP from config.yaml
|
|
110
116
|
```
|
|
111
117
|
|
|
112
118
|
**Flags:**
|
|
@@ -121,25 +127,18 @@ urkit teach # reads IP from config.yaml
|
|
|
121
127
|
| `--gripper-close-on-high` | Digital polarity: `true` or `false` |
|
|
122
128
|
| `--points` | Path to `points.db` file (overrides config) |
|
|
123
129
|
| `--config` | Path to config file (default: `config.yaml` in project root or CWD) |
|
|
130
|
+
| `-e`, `--expert` | Disable safety speed clamping (full speed for goto/tcp-down) |
|
|
124
131
|
| `-v`, `--verbose` | Show verbose output (debug connection issues) |
|
|
125
132
|
|
|
126
133
|
### Points Explorer
|
|
127
134
|
|
|
128
|
-
Browse saved waypoints with real-time search filtering
|
|
135
|
+
Browse saved waypoints with real-time search filtering. No robot connection needed:
|
|
129
136
|
|
|
130
137
|
```bash
|
|
131
138
|
urkit points # uses default points.db
|
|
132
139
|
urkit points test_points.db # use specific database
|
|
133
140
|
```
|
|
134
141
|
|
|
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
142
|
### Key Map
|
|
144
143
|
|
|
145
144
|
All movement and orientation keys support **hold-to-repeat**.
|
|
@@ -191,13 +190,16 @@ All movement and orientation keys support **hold-to-repeat**.
|
|
|
191
190
|
<tr><td><code>X</code></td><td>Open</td></tr>
|
|
192
191
|
<tr><td><code>C</code></td><td>Close</td></tr>
|
|
193
192
|
<tr><td><code>V</code></td><td>Set position (mm)</td></tr>
|
|
193
|
+
<tr><td><code>6</code></td><td>Set speed (0-100)</td></tr>
|
|
194
|
+
<tr><td><code>7</code></td><td>Set force (0-100)</td></tr>
|
|
195
|
+
<tr><td colspan="3">Gripper line shows: `Connected 50.0mm (0%) F=100 S=100`</td></tr>
|
|
194
196
|
</table>
|
|
195
197
|
</td>
|
|
196
198
|
<td align="center" style="width:33%">
|
|
197
199
|
<table>
|
|
198
200
|
<tr><th>Key</th><th>Action</th></tr>
|
|
199
201
|
<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>
|
|
202
|
+
<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
203
|
<tr><td><code>H</code></td><td>Delete saved point</td></tr>
|
|
202
204
|
<tr><td><code>P</code></td><td>Open points explorer</td></tr>
|
|
203
205
|
<tr><td><code>R</code></td><td>Rename saved point</td></tr>
|
|
@@ -217,6 +219,52 @@ All movement and orientation keys support **hold-to-repeat**.
|
|
|
217
219
|
</tr>
|
|
218
220
|
</table>
|
|
219
221
|
|
|
222
|
+
### Joint Display
|
|
223
|
+
|
|
224
|
+
The teach pendant shows live joint angles alongside TCP position and orientation:
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
Position X=+0.432 Y=+0.111 Z=+0.227
|
|
228
|
+
Orientation R=+131.3 P=-121.0 Y= +8.0
|
|
229
|
+
Joints J1=+150.0 J2=+020.0 J3=+160.0
|
|
230
|
+
J4=+050.0 J5=-080.0 J6=+157.0
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Joint angles color-code proximity to mechanical limits:
|
|
234
|
+
|
|
235
|
+
- **Yellow**: within 10% of joint range (warning)
|
|
236
|
+
- **Red**: within 5% of joint range (danger)
|
|
237
|
+
|
|
238
|
+
UR e-Series joint limits:
|
|
239
|
+
|
|
240
|
+
| Joint | Range | Notes |
|
|
241
|
+
|-------|-------|-------|
|
|
242
|
+
| J1 (shoulder pan) | ±360° | Full rotation |
|
|
243
|
+
| J2 (shoulder lift) | ±360° | Full rotation |
|
|
244
|
+
| J3 (elbow) | ±180° | Physically restricted — shoulder lift gets in the way |
|
|
245
|
+
| J4 (wrist 1) | ±360° | Full rotation |
|
|
246
|
+
| J5 (wrist 2) | ±360° | Full rotation |
|
|
247
|
+
| J6 (wrist 3) | ±360° | Tool flange unlimited rotation |
|
|
248
|
+
|
|
249
|
+
Thresholds scale with each joint's range, so warning zones feel proportional across all joints.
|
|
250
|
+
|
|
251
|
+
### Safety
|
|
252
|
+
|
|
253
|
+
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.
|
|
254
|
+
|
|
255
|
+
Delta movements (W/S/A/D/Q/E) use step-size-based velocities that scale with the speed slider set by the user.
|
|
256
|
+
|
|
257
|
+
To disable the slow default and use full speed, pass `--expert` or set `expert_mode: true` in your config:
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
urkit teach 172.31.1.42 --expert
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
```yaml
|
|
264
|
+
# config.yaml
|
|
265
|
+
expert_mode: true
|
|
266
|
+
```
|
|
267
|
+
|
|
220
268
|
---
|
|
221
269
|
|
|
222
270
|
## API Reference
|
|
@@ -226,14 +274,14 @@ All movement and orientation keys support **hold-to-repeat**.
|
|
|
226
274
|
```python
|
|
227
275
|
from urkit import URRobot, ROBOTIQ_HAND_E
|
|
228
276
|
|
|
229
|
-
robot = URRobot(ip="172.31.1.
|
|
277
|
+
robot = URRobot(ip="172.31.1.42", points="points.db", gripper=ROBOTIQ_HAND_E)
|
|
230
278
|
```
|
|
231
279
|
|
|
232
280
|
With custom motion defaults:
|
|
233
281
|
|
|
234
282
|
```python
|
|
235
283
|
robot = URRobot(
|
|
236
|
-
ip="172.31.1.
|
|
284
|
+
ip="172.31.1.42",
|
|
237
285
|
points="points.db",
|
|
238
286
|
gripper=ROBOTIQ_HAND_E,
|
|
239
287
|
default_vel=0.5, # m/s
|
|
@@ -266,39 +314,41 @@ robot.gripper.open() # fully open (blocking by default)
|
|
|
266
314
|
robot.gripper.close() # fully closed, stops on contact
|
|
267
315
|
robot.gripper.open(wait=False) # non-blocking return
|
|
268
316
|
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
|
|
317
|
+
robot.gripper.set_force(50) # grip force: 0-100 (Robotiq only)
|
|
318
|
+
robot.gripper.set_speed(80) # movement speed: 0-100 (Robotiq only)
|
|
271
319
|
```
|
|
272
320
|
|
|
273
321
|
Override preset values for custom fingers:
|
|
274
322
|
|
|
275
323
|
```python
|
|
276
|
-
robot = URRobot(ip="172.31.1.
|
|
324
|
+
robot = URRobot(ip="172.31.1.42", points="points.db", gripper=ROBOTIQ_HAND_E, max_mm=120)
|
|
277
325
|
```
|
|
278
326
|
|
|
279
327
|
#### Digital I/O Grippers
|
|
280
328
|
|
|
281
|
-
|
|
329
|
+
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
330
|
|
|
283
331
|
```python
|
|
284
332
|
from urkit import URRobot, DigitalGripperConfig
|
|
285
333
|
|
|
286
334
|
robot = URRobot(
|
|
287
|
-
ip="172.31.1.
|
|
335
|
+
ip="172.31.1.42",
|
|
288
336
|
points="points.db",
|
|
289
|
-
gripper=DigitalGripperConfig(pin=3),
|
|
337
|
+
gripper=DigitalGripperConfig(pin=3), # pin 3 goes high = close
|
|
290
338
|
)
|
|
291
339
|
|
|
292
|
-
robot.gripper.open() # turn pin off
|
|
293
|
-
robot.gripper.close() # turn pin on
|
|
340
|
+
robot.gripper.open() # turn pin 3 off
|
|
341
|
+
robot.gripper.close() # turn pin 3 on
|
|
294
342
|
```
|
|
295
343
|
|
|
344
|
+
`set_force()` and `set_speed()` are not available for digital grippers.
|
|
345
|
+
|
|
296
346
|
### Points & Motion
|
|
297
347
|
|
|
298
|
-
The points database is optional
|
|
348
|
+
The points database is optional. Create a robot without one and attach later:
|
|
299
349
|
|
|
300
350
|
```python
|
|
301
|
-
robot = URRobot(ip="172.31.1.
|
|
351
|
+
robot = URRobot(ip="172.31.1.42")
|
|
302
352
|
robot.points_db = "points.db"
|
|
303
353
|
```
|
|
304
354
|
|
|
@@ -308,23 +358,50 @@ robot.points_db = "points.db"
|
|
|
308
358
|
robot.move_to("pick") # linear move (default)
|
|
309
359
|
robot.move_to("pick", linear=False) # joint move
|
|
310
360
|
robot.move_to("pick", vel=1.0, acc=0.5) # override speed
|
|
361
|
+
robot.move_to("pick", asynchronous=True) # non-blocking, returns immediately
|
|
311
362
|
```
|
|
312
363
|
|
|
313
|
-
|
|
364
|
+
- **Linear (moveL):** TCP moves in a straight line. Predictable path, slower near complex orientations.
|
|
365
|
+
- **Joint (moveJ):** Each joint moves simultaneously. Faster, but the TCP follows an arc.
|
|
366
|
+
- **Asynchronous:** When `asynchronous=True`, the move runs in the UR controller's background thread and the method returns immediately.
|
|
367
|
+
|
|
368
|
+
#### Non-Blocking Moves
|
|
369
|
+
|
|
370
|
+
Start a move and do other things while it runs:
|
|
314
371
|
|
|
315
372
|
```python
|
|
316
|
-
robot.move_to(
|
|
373
|
+
robot.move_to("pick", asynchronous=True)
|
|
374
|
+
|
|
375
|
+
# Poll until done
|
|
376
|
+
while robot.is_moving():
|
|
377
|
+
time.sleep(0.01)
|
|
378
|
+
|
|
379
|
+
# Or cancel mid-move
|
|
380
|
+
robot.move_to("pick", asynchronous=True)
|
|
381
|
+
while robot.is_moving():
|
|
382
|
+
if should_cancel:
|
|
383
|
+
robot.stop() # sends stopL + stopJ
|
|
384
|
+
break
|
|
385
|
+
time.sleep(0.01)
|
|
317
386
|
```
|
|
318
387
|
|
|
388
|
+
**Teach pendant Go To** uses this pattern internally — Space cancels the move and returns to the menu.
|
|
389
|
+
|
|
390
|
+
#### Pose Format
|
|
391
|
+
|
|
392
|
+
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.
|
|
393
|
+
|
|
319
394
|
#### Offsets
|
|
320
395
|
|
|
396
|
+
Offsets are 6-element lists `[dx, dy, dz, drx, dry, drz]`:
|
|
397
|
+
|
|
321
398
|
```python
|
|
322
399
|
robot.move_to("pick", offset=[0, 0, 0.05, 0, 0, 0]) # 5cm above pick
|
|
323
400
|
```
|
|
324
401
|
|
|
325
402
|
#### Resolve a Pose
|
|
326
403
|
|
|
327
|
-
Get a pose without moving
|
|
404
|
+
Get a pose without moving. Useful for logging, comparisons, or custom motion:
|
|
328
405
|
|
|
329
406
|
```python
|
|
330
407
|
pose = robot.get_pose("pick")
|
|
@@ -338,11 +415,15 @@ robot.move_to(pose) # move to the resolved pose later
|
|
|
338
415
|
from urkit import MoveFrame
|
|
339
416
|
|
|
340
417
|
robot.move_frame = MoveFrame.TOOL # default is BASE
|
|
341
|
-
robot.
|
|
418
|
+
robot.move_relative([0, 0, 0.05, 0, 0, 0]) # 5cm along tool Z
|
|
342
419
|
```
|
|
343
420
|
|
|
344
|
-
- **BASE** (default):
|
|
345
|
-
- **TOOL**:
|
|
421
|
+
- **BASE** (default): delta relative to robot base
|
|
422
|
+
- **TOOL**: delta relative to TCP orientation
|
|
423
|
+
|
|
424
|
+
#### Points are tool-agnostic
|
|
425
|
+
|
|
426
|
+
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
427
|
|
|
347
428
|
#### Point Management
|
|
348
429
|
|
|
@@ -359,7 +440,7 @@ robot.import_points("backup.json")
|
|
|
359
440
|
|
|
360
441
|
```python
|
|
361
442
|
robot.move_relative([0, 0.01, 0, 0, 0, 0]) # 1cm along Y
|
|
362
|
-
robot.move_relative([0, 0, 0.05], frame=MoveFrame.TOOL)
|
|
443
|
+
robot.move_relative([0, 0, 0.05, 0, 0, 0], frame=MoveFrame.TOOL) # 5cm along tool Z
|
|
363
444
|
```
|
|
364
445
|
|
|
365
446
|
#### Sequences with Blending
|
|
@@ -372,7 +453,7 @@ robot.move_sequence(["a", "b", "c"], blend_radius=0.02)
|
|
|
372
453
|
#### Contact Detection
|
|
373
454
|
|
|
374
455
|
```python
|
|
375
|
-
robot.move_until_contact([0, 0, -0.02, 0, 0, 0])
|
|
456
|
+
robot.move_until_contact([0, 0, -0.02, 0, 0, 0])
|
|
376
457
|
```
|
|
377
458
|
|
|
378
459
|
#### Velocity Control
|
|
@@ -396,11 +477,13 @@ robot.is_freedrive_active # check state
|
|
|
396
477
|
#### Speed Control
|
|
397
478
|
|
|
398
479
|
```python
|
|
399
|
-
robot.
|
|
400
|
-
robot.
|
|
480
|
+
robot.stop() # stop current move immediately (stopL + stopJ)
|
|
481
|
+
robot.speed_stop() # stop velocity-controlled motion (not E-stop)
|
|
482
|
+
robot.set_speed_slider(0.5) # 50% velocity cap
|
|
483
|
+
robot.get_speed_slider() # read current slider (0.0-1.0)
|
|
401
484
|
```
|
|
402
485
|
|
|
403
|
-
The speed slider
|
|
486
|
+
The speed slider controls the pendant's speed multiplier. It's global, persistent, and affects all motion commands.
|
|
404
487
|
|
|
405
488
|
#### Inverse Kinematics
|
|
406
489
|
|
|
@@ -415,11 +498,27 @@ pose = robot.get_tcp_pose() # [x, y, z, rx, ry, rz]
|
|
|
415
498
|
joints = robot.get_joint_positions() # [j0..j5]
|
|
416
499
|
force = robot.get_tcp_force() # [fx, fy, fz, mx, my, mz]
|
|
417
500
|
mode = robot.get_robot_mode() # "REMOTE_CONTROL", "SERVOING", etc.
|
|
418
|
-
scaling = robot.get_speed_scaling() # 0.0-1.0
|
|
419
501
|
payload = robot.get_payload() # kg
|
|
502
|
+
robot.is_moving() # bool — any joint/TCP velocity non-zero
|
|
420
503
|
robot.is_protective_stopped() # bool
|
|
421
504
|
robot.is_emergency_stopped() # bool
|
|
422
505
|
robot.current_point() # {"pose": [...], "joints": [...]}
|
|
506
|
+
robot.is_at_pose(target) # bool — TCP within 1mm / 0.5°
|
|
507
|
+
robot.is_at_joints(target) # bool — all joints within 0.001 rad
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
`is_moving()` is the simplest way to poll — `is_at_pose()` / `is_at_joints()` for precise target checking:
|
|
511
|
+
|
|
512
|
+
```python
|
|
513
|
+
robot.move_to("pick", asynchronous=True)
|
|
514
|
+
|
|
515
|
+
# Simple: wait until robot stops
|
|
516
|
+
while robot.is_moving():
|
|
517
|
+
time.sleep(0.01)
|
|
518
|
+
|
|
519
|
+
# Precise: check against specific target
|
|
520
|
+
while not robot.is_at_pose(target_pose):
|
|
521
|
+
time.sleep(0.01)
|
|
423
522
|
```
|
|
424
523
|
|
|
425
524
|
### Digital I/O
|
|
@@ -453,11 +552,12 @@ URKit searches for `config.yaml` in this order:
|
|
|
453
552
|
|
|
454
553
|
| Key | Description | Example |
|
|
455
554
|
|-----|-------------|---------|
|
|
456
|
-
| `robot_ip` | Robot IP address | `
|
|
555
|
+
| `robot_ip` | Robot IP address | `172.31.1.42` |
|
|
457
556
|
| `points_path` | Path to SQLite points database | `points.db` |
|
|
458
557
|
| `gripper` | Gripper preset name | `hand-e`, `2f-85`, `2f-140`, `digital` |
|
|
459
558
|
| `default_vel` | Default linear velocity (m/s) | `0.5` |
|
|
460
559
|
| `default_acc` | Default linear acceleration (m/s²) | `0.3` |
|
|
560
|
+
| `expert_mode` | Disable safety speed clamping | `false` |
|
|
461
561
|
|
|
462
562
|
### Gripper Config
|
|
463
563
|
|
|
@@ -477,17 +577,17 @@ gripper_config:
|
|
|
477
577
|
|
|
478
578
|
### CLI Override Precedence
|
|
479
579
|
|
|
480
|
-
1. **CLI flags
|
|
481
|
-
2. **Config file
|
|
482
|
-
3. **Built-in defaults
|
|
580
|
+
1. **CLI flags.** `urkit teach 172.31.1.42 --gripper none`
|
|
581
|
+
2. **Config file.** Values from `config.yaml`
|
|
582
|
+
3. **Built-in defaults.** `points.db`, no gripper, 0.5 m/s velocity
|
|
483
583
|
|
|
484
584
|
### Saving Config
|
|
485
585
|
|
|
486
586
|
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
587
|
|
|
488
588
|
```bash
|
|
489
|
-
urkit teach 172.31.1.
|
|
490
|
-
urkit teach
|
|
589
|
+
urkit teach 172.31.1.42 --gripper hand-e # test, then press Y
|
|
590
|
+
urkit teach # next time: reads from config
|
|
491
591
|
```
|
|
492
592
|
|
|
493
593
|
Multiple workcells:
|
|
@@ -505,7 +605,7 @@ from urkit import load_config, resolve_config
|
|
|
505
605
|
config = load_config() # auto-resolve
|
|
506
606
|
config = load_config("/path/to/my.yaml") # explicit path
|
|
507
607
|
path = resolve_config() # returns Path or None
|
|
508
|
-
robot = URRobot.from_config({"robot_ip": "172.31.1.
|
|
608
|
+
robot = URRobot.from_config({"robot_ip": "172.31.1.42", "gripper": "2f-85"})
|
|
509
609
|
```
|
|
510
610
|
|
|
511
611
|
---
|
|
@@ -517,7 +617,6 @@ robot = URRobot.from_config({"robot_ip": "172.31.1.200", "gripper": "2f-85"})
|
|
|
517
617
|
URKit doesn't try to wrap everything. Access the raw `ur_rtde` interfaces for advanced features:
|
|
518
618
|
|
|
519
619
|
```python
|
|
520
|
-
robot.rtde_control.moveUntilContact([0, 0, -0.02, 0, 0, 0])
|
|
521
620
|
robot.rtde_control.forceMode(...)
|
|
522
621
|
robot.rtde_control.servoJ(...)
|
|
523
622
|
robot.rtde_receive.getActualCurrent()
|
|
@@ -537,10 +636,10 @@ robot.reconnect_rtde() # reconnect after a drop
|
|
|
537
636
|
### Error Handling
|
|
538
637
|
|
|
539
638
|
```python
|
|
540
|
-
from urkit import URKitError,
|
|
639
|
+
from urkit import URKitError, MotionError, PointError
|
|
541
640
|
|
|
542
641
|
try:
|
|
543
|
-
robot = URRobot(ip="172.31.1.
|
|
642
|
+
robot = URRobot(ip="172.31.1.42", points="points.db")
|
|
544
643
|
except RobotNotInRemoteModeError:
|
|
545
644
|
print("Enable remote control on the teach pendant!")
|
|
546
645
|
except RtdeRegisterConflictError:
|
|
@@ -548,3 +647,36 @@ except RtdeRegisterConflictError:
|
|
|
548
647
|
except URKitError as e:
|
|
549
648
|
print(f"Error: {e}")
|
|
550
649
|
```
|
|
650
|
+
|
|
651
|
+
Common runtime errors:
|
|
652
|
+
|
|
653
|
+
| Exception | When |
|
|
654
|
+
|-----------|------|
|
|
655
|
+
| `MotionError` | Unreachable pose, bad TCP offset, freedrive failure |
|
|
656
|
+
| `PointError` | Point not found, no points database configured |
|
|
657
|
+
| `GripperError` | Gripper activation or communication failure |
|
|
658
|
+
| `URKitIOError` | Invalid pin number, I/O read/write failure |
|
|
659
|
+
| `TelemetryError` | Cannot read pose, joints, force, etc. |
|
|
660
|
+
|
|
661
|
+
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.
|
|
662
|
+
|
|
663
|
+
### Connection Notes
|
|
664
|
+
|
|
665
|
+
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.
|
|
666
|
+
|
|
667
|
+
---
|
|
668
|
+
|
|
669
|
+
## Changelog
|
|
670
|
+
|
|
671
|
+
See [CHANGELOG.md](CHANGELOG.md) for the full version history.
|
|
672
|
+
|
|
673
|
+
### Recent Changes
|
|
674
|
+
|
|
675
|
+
- **v3.2** — Gripper speed/force keys (6/7), force/speed display
|
|
676
|
+
- **v3.1** — Async motion, Space cancel, progress bar, joint display
|
|
677
|
+
- **v0.3.0** — Safe/expert mode, speed_stop on exit, safety features
|
|
678
|
+
- **v0.2.1** — `get_pose()` method
|
|
679
|
+
- **v0.2.0** — README restructure
|
|
680
|
+
- **v0.1.1** — `--gripper none`, `--config` flag, save config on demand
|
|
681
|
+
- **v0.1.0** — Initial release
|
|
682
|
+
|