urkit 0.1.0__py3-none-any.whl
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/__init__.py +99 -0
- urkit/__main__.py +116 -0
- urkit/cli/__init__.py +6 -0
- urkit/cli/colors.py +99 -0
- urkit/cli/connection_monitor.py +154 -0
- urkit/cli/points.py +293 -0
- urkit/cli/teach.py +1181 -0
- urkit/config.py +78 -0
- urkit/connection.py +580 -0
- urkit/exceptions.py +51 -0
- urkit/geometry.py +413 -0
- urkit/gripper/__init__.py +36 -0
- urkit/gripper/base.py +116 -0
- urkit/gripper/digital.py +140 -0
- urkit/gripper/presets.py +113 -0
- urkit/gripper/robotiq.py +322 -0
- urkit/gripper/robotiq_preamble.py +1356 -0
- urkit/io.py +311 -0
- urkit/motion.py +504 -0
- urkit/points.py +277 -0
- urkit/robot.py +1510 -0
- urkit/telemetry.py +177 -0
- urkit-0.1.0.dist-info/METADATA +612 -0
- urkit-0.1.0.dist-info/RECORD +27 -0
- urkit-0.1.0.dist-info/WHEEL +5 -0
- urkit-0.1.0.dist-info/entry_points.txt +2 -0
- urkit-0.1.0.dist-info/top_level.txt +1 -0
urkit/io.py
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
"""Digital I/O operations for Universal Robots e-Series.
|
|
2
|
+
|
|
3
|
+
Reads and writes digital I/O signals via the RTDE IO and
|
|
4
|
+
receive interfaces. All pins are addressed by their hardware
|
|
5
|
+
number (0–17) — no separate "standard" vs "configurable" methods.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
from typing import TYPE_CHECKING, Union
|
|
12
|
+
|
|
13
|
+
import time
|
|
14
|
+
from urkit.exceptions import URKitIOError as IOError
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from rtde_io import RTDEIOInterface
|
|
18
|
+
from rtde_receive import RTDEReceiveInterface
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class IO:
|
|
24
|
+
"""Digital I/O operations via RTDE.
|
|
25
|
+
|
|
26
|
+
Wraps the RTDE interfaces with typed, documented accessors for
|
|
27
|
+
digital I/O signals. All methods raise IOError on failure.
|
|
28
|
+
|
|
29
|
+
Pins are addressed by their hardware number:
|
|
30
|
+
- 0–7: standard digital I/O
|
|
31
|
+
- 8–15: configurable digital I/O
|
|
32
|
+
- 16–17: tool digital I/O
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
rtde_io: RTDEIOInterface instance (for setting outputs).
|
|
36
|
+
rtde_receive: RTDEReceiveInterface instance (for reading inputs/outputs).
|
|
37
|
+
|
|
38
|
+
Example:
|
|
39
|
+
>>> io = IO(rtde_io, rtde_r)
|
|
40
|
+
>>> io.set_digital_output(0, True)
|
|
41
|
+
>>> io.set_digital_outputs({0: True, 1: False, 8: True})
|
|
42
|
+
>>> value = io.get_digital_output(0)
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(
|
|
46
|
+
self,
|
|
47
|
+
rtde_io: "RTDEIOInterface",
|
|
48
|
+
rtde_receive: "RTDEReceiveInterface",
|
|
49
|
+
) -> None:
|
|
50
|
+
self._rtde_io = rtde_io
|
|
51
|
+
self._rtde_r = rtde_receive
|
|
52
|
+
|
|
53
|
+
# ── Digital Outputs ────────────────────────────────────────────
|
|
54
|
+
|
|
55
|
+
def set_digital_output(self, pin: int, value: bool) -> None:
|
|
56
|
+
"""Set a digital output pin.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
pin: Digital output pin index (0–15 on e-Series).
|
|
60
|
+
Pins 0–7 are standard, 8–15 are configurable.
|
|
61
|
+
value: True to set high, False to set low.
|
|
62
|
+
|
|
63
|
+
Raises:
|
|
64
|
+
IOError: If the pin is invalid or the operation fails.
|
|
65
|
+
"""
|
|
66
|
+
if not isinstance(value, bool):
|
|
67
|
+
raise IOError(
|
|
68
|
+
f"Digital output value must be bool, got {type(value).__name__}."
|
|
69
|
+
)
|
|
70
|
+
if not 0 <= pin <= 15:
|
|
71
|
+
raise IOError(
|
|
72
|
+
f"Digital output pin must be 0–15, got {pin}. "
|
|
73
|
+
"Pins 0–7 are standard, 8–15 are configurable."
|
|
74
|
+
)
|
|
75
|
+
try:
|
|
76
|
+
if pin < 8:
|
|
77
|
+
self._rtde_io.setStandardDigitalOut(pin, value)
|
|
78
|
+
else:
|
|
79
|
+
self._rtde_io.setConfigurableDigitalOut(pin - 8, value)
|
|
80
|
+
except Exception as e:
|
|
81
|
+
raise IOError(
|
|
82
|
+
f"Failed to set digital output {pin} to {value}: {e}"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
def set_digital_outputs(
|
|
86
|
+
self, values: Union[bool, dict[int, bool]]
|
|
87
|
+
) -> None:
|
|
88
|
+
"""Set multiple digital outputs at once.
|
|
89
|
+
|
|
90
|
+
Pass a dict of ``{pin: value}`` pairs, or a single bool
|
|
91
|
+
to set all pins 0–15 to the same value.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
values: Dict mapping pin numbers to bool values,
|
|
95
|
+
or a single bool to apply to all pins.
|
|
96
|
+
|
|
97
|
+
Raises:
|
|
98
|
+
IOError: If any pin is invalid or the operation fails.
|
|
99
|
+
|
|
100
|
+
Example:
|
|
101
|
+
>>> # Set specific pins
|
|
102
|
+
>>> io.set_digital_outputs({0: True, 1: False, 8: True})
|
|
103
|
+
>>> # Clear all outputs
|
|
104
|
+
>>> io.set_digital_outputs(False)
|
|
105
|
+
"""
|
|
106
|
+
if isinstance(values, bool):
|
|
107
|
+
pins = {p: values for p in range(16)}
|
|
108
|
+
else:
|
|
109
|
+
pins = dict(values)
|
|
110
|
+
|
|
111
|
+
for pin, value in pins.items():
|
|
112
|
+
self.set_digital_output(pin, value)
|
|
113
|
+
|
|
114
|
+
def get_digital_output(self, pin: int) -> bool:
|
|
115
|
+
"""Get the current state of a digital output.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
pin: Digital output pin index (0–17 on e-Series).
|
|
119
|
+
Pins 0–7 are standard, 8–15 configurable, 16–17 tool.
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
True if the output is high, False if low.
|
|
123
|
+
|
|
124
|
+
Raises:
|
|
125
|
+
IOError: If the pin is invalid or the read fails.
|
|
126
|
+
"""
|
|
127
|
+
if not 0 <= pin <= 17:
|
|
128
|
+
raise IOError(
|
|
129
|
+
f"Digital output pin must be 0–17, got {pin}."
|
|
130
|
+
)
|
|
131
|
+
try:
|
|
132
|
+
return bool(self._rtde_r.getDigitalOutState(pin))
|
|
133
|
+
except Exception as e:
|
|
134
|
+
raise IOError(
|
|
135
|
+
f"Failed to read digital output {pin}: {e}"
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
# ── Digital Inputs ─────────────────────────────────────────────
|
|
139
|
+
|
|
140
|
+
def get_digital_input(self, pin: int) -> bool:
|
|
141
|
+
"""Get the current state of a digital input.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
pin: Digital input pin index (0–17 on e-Series).
|
|
145
|
+
Pins 0–7 are standard, 8–15 configurable, 16–17 tool.
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
True if high, False if low.
|
|
149
|
+
|
|
150
|
+
Raises:
|
|
151
|
+
IOError: If the pin is invalid or the read fails.
|
|
152
|
+
"""
|
|
153
|
+
if not 0 <= pin <= 17:
|
|
154
|
+
raise IOError(
|
|
155
|
+
f"Digital input pin must be 0–17, got {pin}."
|
|
156
|
+
)
|
|
157
|
+
try:
|
|
158
|
+
return bool(self._rtde_r.getDigitalInState(pin))
|
|
159
|
+
except Exception as e:
|
|
160
|
+
raise IOError(
|
|
161
|
+
f"Failed to read digital input {pin}: {e}"
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
def get_tool_input(self, pin: int) -> bool:
|
|
165
|
+
"""Get the current state of a tool digital input.
|
|
166
|
+
|
|
167
|
+
Tool inputs correspond to pins 16–17 on the robot's I/O board
|
|
168
|
+
(the tool connector). Use pin 0 or 1 to access them.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
pin: Tool input pin index (0–1).
|
|
172
|
+
|
|
173
|
+
Returns:
|
|
174
|
+
True if high, False if low.
|
|
175
|
+
|
|
176
|
+
Raises:
|
|
177
|
+
IOError: If the pin is invalid or the read fails.
|
|
178
|
+
"""
|
|
179
|
+
if not 0 <= pin <= 1:
|
|
180
|
+
raise IOError(f"Tool input pin must be 0–1, got {pin}.")
|
|
181
|
+
try:
|
|
182
|
+
return bool(self._rtde_r.getDigitalInState(16 + pin))
|
|
183
|
+
except Exception as e:
|
|
184
|
+
raise IOError(
|
|
185
|
+
f"Failed to read tool digital input {pin}: {e}"
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
def get_tool_output(self, pin: int) -> bool:
|
|
189
|
+
"""Get the current state of a tool digital output.
|
|
190
|
+
|
|
191
|
+
Tool outputs correspond to pins 16–17 on the robot's I/O board.
|
|
192
|
+
Tool outputs are configured in the robot's I/O mapping and cannot
|
|
193
|
+
be set directly via RTDE — they are controlled by the robot
|
|
194
|
+
controller based on the configured mode (auto/manual). This method
|
|
195
|
+
reads the actual output state.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
pin: Tool output pin index (0–1).
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
True if high, False if low.
|
|
202
|
+
|
|
203
|
+
Raises:
|
|
204
|
+
IOError: If the pin is invalid or the read fails.
|
|
205
|
+
"""
|
|
206
|
+
if not 0 <= pin <= 1:
|
|
207
|
+
raise IOError(f"Tool output pin must be 0–1, got {pin}.")
|
|
208
|
+
try:
|
|
209
|
+
return bool(self._rtde_r.getDigitalOutState(16 + pin))
|
|
210
|
+
except Exception as e:
|
|
211
|
+
raise IOError(
|
|
212
|
+
f"Failed to read tool digital output {pin}: {e}"
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
# ── Analog ─────────────────────────────────────────────────────
|
|
216
|
+
|
|
217
|
+
def get_analog_input(self, pin: int) -> float:
|
|
218
|
+
"""Get the current value of a standard analog input.
|
|
219
|
+
|
|
220
|
+
Reads from the robot's analog input channel (0–10V or 4–20mA
|
|
221
|
+
depending on the robot's configuration).
|
|
222
|
+
|
|
223
|
+
Args:
|
|
224
|
+
pin: Analog input pin index (0–1).
|
|
225
|
+
|
|
226
|
+
Returns:
|
|
227
|
+
Analog value in volts or amperes.
|
|
228
|
+
|
|
229
|
+
Raises:
|
|
230
|
+
IOError: If the pin is invalid or the read fails.
|
|
231
|
+
"""
|
|
232
|
+
if pin == 0:
|
|
233
|
+
read_fn = self._rtde_r.getStandardAnalogInput0
|
|
234
|
+
elif pin == 1:
|
|
235
|
+
read_fn = self._rtde_r.getStandardAnalogInput1
|
|
236
|
+
else:
|
|
237
|
+
raise IOError(f"Analog input pin must be 0–1, got {pin}.")
|
|
238
|
+
try:
|
|
239
|
+
return float(read_fn())
|
|
240
|
+
except Exception as e:
|
|
241
|
+
raise IOError(
|
|
242
|
+
f"Failed to read analog input {pin}: {e}"
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
def get_analog_output(self, pin: int) -> float:
|
|
246
|
+
"""Get the current value of a standard analog output.
|
|
247
|
+
|
|
248
|
+
Args:
|
|
249
|
+
pin: Analog output pin index (0–1).
|
|
250
|
+
|
|
251
|
+
Returns:
|
|
252
|
+
Analog value in volts or amperes.
|
|
253
|
+
|
|
254
|
+
Raises:
|
|
255
|
+
IOError: If the pin is invalid or the read fails.
|
|
256
|
+
"""
|
|
257
|
+
if pin == 0:
|
|
258
|
+
read_fn = self._rtde_r.getStandardAnalogOutput0
|
|
259
|
+
elif pin == 1:
|
|
260
|
+
read_fn = self._rtde_r.getStandardAnalogOutput1
|
|
261
|
+
else:
|
|
262
|
+
raise IOError(f"Analog output pin must be 0–1, got {pin}.")
|
|
263
|
+
try:
|
|
264
|
+
return float(read_fn())
|
|
265
|
+
except Exception as e:
|
|
266
|
+
raise IOError(
|
|
267
|
+
f"Failed to read analog output {pin}: {e}"
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
# ── Wait ───────────────────────────────────────────────────────
|
|
271
|
+
|
|
272
|
+
def wait_for_input(
|
|
273
|
+
self,
|
|
274
|
+
pin: int,
|
|
275
|
+
value: bool = True,
|
|
276
|
+
*,
|
|
277
|
+
timeout: float = 10.0,
|
|
278
|
+
) -> bool:
|
|
279
|
+
"""Block until a digital input reaches the desired value.
|
|
280
|
+
|
|
281
|
+
Polls the specified digital input at ~50 Hz until it matches
|
|
282
|
+
*value* or *timeout* seconds have elapsed.
|
|
283
|
+
|
|
284
|
+
Args:
|
|
285
|
+
pin: Digital input pin index (0–17).
|
|
286
|
+
value: Desired value (True for high, False for low).
|
|
287
|
+
timeout: Maximum wait time in seconds (default 10.0).
|
|
288
|
+
|
|
289
|
+
Returns:
|
|
290
|
+
True if the input reached the desired value, False if timed out.
|
|
291
|
+
|
|
292
|
+
Raises:
|
|
293
|
+
IOError: If the pin is invalid or the read fails.
|
|
294
|
+
|
|
295
|
+
Example:
|
|
296
|
+
>>> # Wait for a limit switch on pin 0
|
|
297
|
+
>>> if not io.wait_for_input(0, True, timeout=5.0):
|
|
298
|
+
... raise TimeoutError("Limit switch not triggered")
|
|
299
|
+
"""
|
|
300
|
+
if not 0 <= pin <= 17:
|
|
301
|
+
raise IOError(f"Digital input pin must be 0–17, got {pin}.")
|
|
302
|
+
|
|
303
|
+
deadline = time.monotonic() + timeout
|
|
304
|
+
while time.monotonic() < deadline:
|
|
305
|
+
try:
|
|
306
|
+
if bool(self._rtde_r.getDigitalInState(pin)) == value:
|
|
307
|
+
return True
|
|
308
|
+
except Exception as e:
|
|
309
|
+
raise IOError(f"Failed to read input pin {pin}: {e}")
|
|
310
|
+
time.sleep(0.02) # ~50 Hz polling
|
|
311
|
+
return False
|