xarm-python-sdk 1.15.2__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.
- xarm/__init__.py +2 -0
- xarm/build_backend.py +17 -0
- xarm/core/__init__.py +2 -0
- xarm/core/comm/__init__.py +5 -0
- xarm/core/comm/base.py +303 -0
- xarm/core/comm/serial_port.py +44 -0
- xarm/core/comm/socket_port.py +150 -0
- xarm/core/comm/uxbus_cmd_protocol.py +100 -0
- xarm/core/config/__init__.py +0 -0
- xarm/core/config/x_code.py +1427 -0
- xarm/core/config/x_config.py +553 -0
- xarm/core/utils/__init__.py +3 -0
- xarm/core/utils/convert.py +124 -0
- xarm/core/utils/crc16.py +76 -0
- xarm/core/utils/debug_print.py +21 -0
- xarm/core/utils/log.py +98 -0
- xarm/core/version.py +1 -0
- xarm/core/wrapper/__init__.py +11 -0
- xarm/core/wrapper/uxbus_cmd.py +1457 -0
- xarm/core/wrapper/uxbus_cmd_ser.py +94 -0
- xarm/core/wrapper/uxbus_cmd_tcp.py +305 -0
- xarm/tools/__init__.py +0 -0
- xarm/tools/blockly/__init__.py +1 -0
- xarm/tools/blockly/_blockly_base.py +416 -0
- xarm/tools/blockly/_blockly_handler.py +1338 -0
- xarm/tools/blockly/_blockly_highlight.py +94 -0
- xarm/tools/blockly/_blockly_node.py +61 -0
- xarm/tools/blockly/_blockly_tool.py +480 -0
- xarm/tools/blockly_tool.py +1864 -0
- xarm/tools/gcode.py +90 -0
- xarm/tools/list_ports.py +39 -0
- xarm/tools/modbus_tcp.py +205 -0
- xarm/tools/threads.py +30 -0
- xarm/tools/utils.py +36 -0
- xarm/version.py +1 -0
- xarm/wrapper/__init__.py +1 -0
- xarm/wrapper/studio_api.py +34 -0
- xarm/wrapper/xarm_api.py +4416 -0
- xarm/x3/__init__.py +2 -0
- xarm/x3/base.py +2638 -0
- xarm/x3/base_board.py +198 -0
- xarm/x3/code.py +62 -0
- xarm/x3/decorator.py +104 -0
- xarm/x3/events.py +166 -0
- xarm/x3/ft_sensor.py +264 -0
- xarm/x3/gpio.py +457 -0
- xarm/x3/grammar_async.py +21 -0
- xarm/x3/grammar_coroutine.py +24 -0
- xarm/x3/gripper.py +830 -0
- xarm/x3/modbus_tcp.py +84 -0
- xarm/x3/parse.py +110 -0
- xarm/x3/record.py +216 -0
- xarm/x3/report.py +204 -0
- xarm/x3/robotiq.py +220 -0
- xarm/x3/servo.py +485 -0
- xarm/x3/studio.py +138 -0
- xarm/x3/track.py +424 -0
- xarm/x3/utils.py +43 -0
- xarm/x3/xarm.py +1928 -0
- xarm_python_sdk-1.15.2.dist-info/METADATA +103 -0
- xarm_python_sdk-1.15.2.dist-info/RECORD +63 -0
- xarm_python_sdk-1.15.2.dist-info/WHEEL +4 -0
- xarm_python_sdk-1.15.2.dist-info/licenses/LICENSE +27 -0
xarm/x3/gpio.py
ADDED
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Software License Agreement (BSD License)
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2019, UFACTORY, Inc.
|
|
5
|
+
# All rights reserved.
|
|
6
|
+
#
|
|
7
|
+
# Author: Vinman <vinman.wen@ufactory.cc> <vinman.cub@gmail.com>
|
|
8
|
+
|
|
9
|
+
import time
|
|
10
|
+
from ..core.utils.log import logger
|
|
11
|
+
from ..core.config.x_config import XCONF
|
|
12
|
+
from .code import APIState
|
|
13
|
+
from .base import Base
|
|
14
|
+
from .decorator import xarm_is_connected, xarm_is_ready, xarm_wait_until_not_pause, xarm_is_not_simulation_mode, xarm_wait_until_cmdnum_lt_max
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class GPIO(Base):
|
|
18
|
+
def __init__(self):
|
|
19
|
+
super(GPIO, self).__init__()
|
|
20
|
+
self.cgpio_state = {
|
|
21
|
+
'digital': [-1] * 8,
|
|
22
|
+
'analog': [9999] * 2
|
|
23
|
+
}
|
|
24
|
+
self.tgpio_state = {
|
|
25
|
+
'digital': [-1] * 5,
|
|
26
|
+
'analog': [9999] * 2
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
# @xarm_is_connected(_type='set')
|
|
30
|
+
# def set_tgpio_addr_16(self, addr, value):
|
|
31
|
+
# ret = self.arm_cmd.tgpio_addr_w16(addr, value)
|
|
32
|
+
# return ret[0]
|
|
33
|
+
#
|
|
34
|
+
# @xarm_is_connected(_type='get')
|
|
35
|
+
# def get_tgpio_addr_16(self, addr):
|
|
36
|
+
# ret = self.arm_cmd.tgpio_addr_r16(addr)
|
|
37
|
+
# return ret[0], ret[1]
|
|
38
|
+
#
|
|
39
|
+
# @xarm_is_connected(_type='set')
|
|
40
|
+
# def set_tgpio_addr_32(self, addr, value):
|
|
41
|
+
# ret = self.arm_cmd.tgpio_addr_w32(addr, value)
|
|
42
|
+
# return ret[0]
|
|
43
|
+
#
|
|
44
|
+
# @xarm_is_connected(_type='get')
|
|
45
|
+
# def get_tgpio_addr_32(self, addr):
|
|
46
|
+
# ret = self.arm_cmd.tgpio_addr_r32(addr)
|
|
47
|
+
# return ret[0], ret[1]
|
|
48
|
+
|
|
49
|
+
@xarm_is_connected(_type='get')
|
|
50
|
+
def get_tgpio_version(self):
|
|
51
|
+
versions = ['*', '*', '*']
|
|
52
|
+
ret1 = self.arm_cmd.tgpio_addr_r16(0x0801)
|
|
53
|
+
ret2 = self.arm_cmd.tgpio_addr_r16(0x0802)
|
|
54
|
+
ret3 = self.arm_cmd.tgpio_addr_r16(0x0803)
|
|
55
|
+
|
|
56
|
+
code = 0
|
|
57
|
+
|
|
58
|
+
if ret1[0] == 0 and len(ret1) == 2:
|
|
59
|
+
versions[0] = ret1[1]
|
|
60
|
+
else:
|
|
61
|
+
code = ret1[0]
|
|
62
|
+
|
|
63
|
+
if ret2[0] == 0 and len(ret2) == 2:
|
|
64
|
+
versions[1] = ret2[1]
|
|
65
|
+
else:
|
|
66
|
+
code = ret2[0]
|
|
67
|
+
|
|
68
|
+
if ret3[0] == 0 and len(ret3) == 2:
|
|
69
|
+
versions[2] = ret3[1]
|
|
70
|
+
else:
|
|
71
|
+
code = ret3[0]
|
|
72
|
+
# if code != 0:
|
|
73
|
+
# _, err_warn = self.get_err_warn_code()
|
|
74
|
+
# if _ in [0, 1, 2]:
|
|
75
|
+
# if err_warn[0] not in [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 28]:
|
|
76
|
+
# versions = [ret1[1], ret2[1], ret3[1]]
|
|
77
|
+
|
|
78
|
+
return code, '.'.join(map(str, versions))
|
|
79
|
+
|
|
80
|
+
@xarm_is_connected(_type='get')
|
|
81
|
+
def get_tgpio_digital(self, ionum=None):
|
|
82
|
+
assert ionum is None or ionum == 0 or ionum == 1 or ionum == 2 or ionum == 3 or ionum == 4, 'The value of parameter ionum can only be 0 or 1 or None.'
|
|
83
|
+
if self.check_is_simulation_robot():
|
|
84
|
+
return 0, [0, 0, 0, 0] if ionum is None else 0
|
|
85
|
+
if ionum == 2:
|
|
86
|
+
# Only available for Lite6 and 850
|
|
87
|
+
ret = self.arm_cmd.tgpio_addr_r16(0x0A12)
|
|
88
|
+
return ret[0], ret[1] & 0x0001
|
|
89
|
+
else:
|
|
90
|
+
ret = self.arm_cmd.tgpio_get_digital()
|
|
91
|
+
if ret[0] == 0:
|
|
92
|
+
self.tgpio_state['digital'] = ret[1:]
|
|
93
|
+
return ret[0], ret[1:] if ionum is None else ret[ionum + 1 if ionum < 3 else ionum]
|
|
94
|
+
|
|
95
|
+
@xarm_is_connected(_type='get')
|
|
96
|
+
def get_tool_digital_input(self, ionum=None):
|
|
97
|
+
assert ionum is None or ionum == 0 or ionum == 1 or ionum == 2 or ionum == 3 or ionum == 4, 'The value of parameter ionum can only be 0 or 1 or None.'
|
|
98
|
+
if self.check_is_simulation_robot():
|
|
99
|
+
return 0, [0, 0, 0, 0, 0] if ionum is None else 0
|
|
100
|
+
if ionum == 2:
|
|
101
|
+
# Only available for Lite6 and 850
|
|
102
|
+
ret = self.arm_cmd.tgpio_addr_r16(0x0A12)
|
|
103
|
+
return ret[0], ret[1] & 0x0001
|
|
104
|
+
elif isinstance(ionum, int):
|
|
105
|
+
ret = self.arm_cmd.tgpio_get_digital()
|
|
106
|
+
if ret[0] == 0:
|
|
107
|
+
self.tgpio_state['digital'] = ret[1:]
|
|
108
|
+
return ret[0], ret[ionum+1 if ionum < 3 else ionum]
|
|
109
|
+
else:
|
|
110
|
+
ret1 = self.arm_cmd.tgpio_get_digital()
|
|
111
|
+
if ret1[0] == 0:
|
|
112
|
+
self.tgpio_state['digital'] = ret1[1:]
|
|
113
|
+
ret2 = [0]
|
|
114
|
+
if self.is_lite6 or self.is_850:
|
|
115
|
+
ret2 = self.arm_cmd.tgpio_addr_r16(0x0A12)
|
|
116
|
+
ret1.insert(3, ret2[1])
|
|
117
|
+
return ret1[0] or ret2[0], ret1[1:4] if self.is_lite6 else ret1[1:] if self.is_850 or int(self.sn[2:6]) >= 1305 else ret1[1:3]
|
|
118
|
+
|
|
119
|
+
@xarm_is_connected(_type='get')
|
|
120
|
+
def get_tgpio_output_digital(self, ionum=None):
|
|
121
|
+
ret_li = [0, 0, 0, 0, 0]
|
|
122
|
+
assert ionum is None or ionum == 0 or ionum == 1 or ionum == 2 or ionum == 3 or ionum == 4, 'The value of parameter ionum can only be 0 or 1 or None.'
|
|
123
|
+
if self.check_is_simulation_robot():
|
|
124
|
+
return 0, [0, 0] if ionum is None else 0
|
|
125
|
+
code, ret = self.arm_cmd.tgpio_addr_r16(0x0A18)
|
|
126
|
+
ret_li[0] = ret & 0b01
|
|
127
|
+
ret_li[1] = ret >> 1 & 0b01
|
|
128
|
+
ret_li[2] = ret >> 4 & 0b01
|
|
129
|
+
ret_li[3] = ret >> 2 & 0b01
|
|
130
|
+
ret_li[4] = ret >> 3 & 0b01
|
|
131
|
+
return code, ret_li if ionum is None else ret_li[ionum]
|
|
132
|
+
|
|
133
|
+
@xarm_wait_until_not_pause
|
|
134
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
135
|
+
@xarm_is_ready(_type='set')
|
|
136
|
+
@xarm_is_not_simulation_mode(ret=0)
|
|
137
|
+
def set_tgpio_digital(self, ionum, value, delay_sec=0, sync=True):
|
|
138
|
+
assert ionum == 0 or ionum == 1 or ionum == 2 or ionum == 3 or ionum == 4, 'The value of parameter ionum can only be 0 or 1.'
|
|
139
|
+
if delay_sec is not None and delay_sec > 0:
|
|
140
|
+
if not sync:
|
|
141
|
+
logger.warning('The sync parameter is ignored when delay_sec is non-zero')
|
|
142
|
+
ret = self.arm_cmd.tgpio_delay_set_digital(ionum if ionum < 2 else ionum-1, value, delay_sec)
|
|
143
|
+
self.log_api_info('API -> set_tgpio_digital(ionum={}, value={}, delay_sec={}) -> code={}'.format(ionum, value, delay_sec, ret[0]), code=ret[0])
|
|
144
|
+
else:
|
|
145
|
+
if not sync and not self.version_is_ge(2, 4, 101):
|
|
146
|
+
logger.warning('The current firmware does not support sync to False. If necessary, please upgrade the firmware to 2.4.101 or later.')
|
|
147
|
+
ret = self.arm_cmd.tgpio_set_digital(ionum+1, value, sync=sync if self.version_is_ge(2, 4, 101) else None)
|
|
148
|
+
self.log_api_info('API -> set_tgpio_digital(ionum={}, value={}) -> code={}'.format(ionum, value, ret[0]), code=ret[0])
|
|
149
|
+
return ret[0]
|
|
150
|
+
|
|
151
|
+
@xarm_is_connected(_type='get')
|
|
152
|
+
def get_tgpio_analog(self, ionum=None):
|
|
153
|
+
if self.check_is_simulation_robot():
|
|
154
|
+
return 0, [0, 0] if ionum is None else 0
|
|
155
|
+
if ionum is None:
|
|
156
|
+
ret1 = self.arm_cmd.tgpio_get_analog1()
|
|
157
|
+
ret2 = self.arm_cmd.tgpio_get_analog2()
|
|
158
|
+
if ret1[0] == 0:
|
|
159
|
+
code = ret2[0]
|
|
160
|
+
else:
|
|
161
|
+
code = ret1[0]
|
|
162
|
+
if ret1[0] == 0:
|
|
163
|
+
self.tgpio_state['analog'][0] = ret1[1]
|
|
164
|
+
if ret2[0] == 0:
|
|
165
|
+
self.tgpio_state['analog'][1] = ret2[1]
|
|
166
|
+
ret = [code, [ret1[1], ret2[1]]]
|
|
167
|
+
else:
|
|
168
|
+
assert ionum == 0 or ionum == 1, 'The value of parameter ionum can only be 0 or 1 or None.'
|
|
169
|
+
if ionum == 0:
|
|
170
|
+
ret = self.arm_cmd.tgpio_get_analog1()
|
|
171
|
+
if ret[0] == 0:
|
|
172
|
+
self.tgpio_state['analog'][0] = ret[1]
|
|
173
|
+
else:
|
|
174
|
+
ret = self.arm_cmd.tgpio_get_analog2()
|
|
175
|
+
if ret[0] == 0:
|
|
176
|
+
self.tgpio_state['analog'][1] = ret[1]
|
|
177
|
+
# if ret[0] != 0:
|
|
178
|
+
# self.get_err_warn_code()
|
|
179
|
+
# if self.error_code != 19:
|
|
180
|
+
# ret[0] = 0
|
|
181
|
+
return ret[0], ret[1]
|
|
182
|
+
|
|
183
|
+
@xarm_is_connected(_type='get')
|
|
184
|
+
def get_cgpio_digital(self, ionum=None):
|
|
185
|
+
assert ionum is None or (isinstance(ionum, int) and 15 >= ionum >= 0)
|
|
186
|
+
if self.check_is_simulation_robot():
|
|
187
|
+
return 0, [1] * (16 if self._control_box_type_is_1300 else 8) if ionum is None else 1
|
|
188
|
+
ret = self.arm_cmd.cgpio_get_auxdigit()
|
|
189
|
+
digitals = [ret[0]]
|
|
190
|
+
for i in range(16 if self._control_box_type_is_1300 else 8):
|
|
191
|
+
digitals.append(ret[1] >> i & 0x0001)
|
|
192
|
+
return digitals[0], digitals[1:] if ionum is None else digitals[ionum+1]
|
|
193
|
+
|
|
194
|
+
@xarm_is_connected(_type='get')
|
|
195
|
+
def get_cgpio_analog(self, ionum=None):
|
|
196
|
+
if self.check_is_simulation_robot():
|
|
197
|
+
return 0, [0, 0] if ionum is None else 0
|
|
198
|
+
if ionum is None:
|
|
199
|
+
ret1 = self.arm_cmd.cgpio_get_analog1()
|
|
200
|
+
ret2 = self.arm_cmd.cgpio_get_analog2()
|
|
201
|
+
if ret1[0] == 0:
|
|
202
|
+
code = ret2[0]
|
|
203
|
+
else:
|
|
204
|
+
code = ret1[0]
|
|
205
|
+
ret = [code, [ret1[1], ret2[1]]]
|
|
206
|
+
else:
|
|
207
|
+
assert ionum == 0 or ionum == 1, 'The value of parameter ionum can only be 0 or 1 or None.'
|
|
208
|
+
if ionum == 0:
|
|
209
|
+
ret = self.arm_cmd.cgpio_get_analog1()
|
|
210
|
+
else:
|
|
211
|
+
ret = self.arm_cmd.cgpio_get_analog2()
|
|
212
|
+
# if ret[0] != 0:
|
|
213
|
+
# self.get_err_warn_code()
|
|
214
|
+
# if self.error_code != 33:
|
|
215
|
+
# ret[0] = 0
|
|
216
|
+
return ret[0], ret[1]
|
|
217
|
+
|
|
218
|
+
@xarm_wait_until_not_pause
|
|
219
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
220
|
+
@xarm_is_ready(_type='set')
|
|
221
|
+
@xarm_is_not_simulation_mode(ret=0)
|
|
222
|
+
def set_cgpio_digital(self, ionum, value, delay_sec=0, sync=True):
|
|
223
|
+
assert isinstance(ionum, int) and 15 >= ionum >= 0
|
|
224
|
+
if delay_sec is not None and delay_sec > 0:
|
|
225
|
+
if not sync:
|
|
226
|
+
logger.warning('The sync parameter is ignored when delay_sec is non-zero')
|
|
227
|
+
ret = self.arm_cmd.cgpio_delay_set_digital(ionum, value, delay_sec)
|
|
228
|
+
self.log_api_info('API -> set_cgpio_digital(ionum={}, value={}, delay_sec={}) -> code={}'.format(ionum, value, delay_sec, ret[0]), code=ret[0])
|
|
229
|
+
else:
|
|
230
|
+
if not sync and not self.version_is_ge(2, 4, 101):
|
|
231
|
+
logger.warning('The current firmware does not support sync to False. If necessary, please upgrade the firmware to 2.4.101 or later.')
|
|
232
|
+
ret = self.arm_cmd.cgpio_set_auxdigit(ionum, value, sync=sync if self.version_is_ge(2, 4, 101) else None)
|
|
233
|
+
self.log_api_info('API -> set_cgpio_digital(ionum={}, value={}) -> code={}'.format(ionum, value, ret[0]), code=ret[0])
|
|
234
|
+
return ret[0]
|
|
235
|
+
|
|
236
|
+
@xarm_wait_until_not_pause
|
|
237
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
238
|
+
@xarm_is_ready(_type='set')
|
|
239
|
+
@xarm_is_not_simulation_mode(ret=0)
|
|
240
|
+
def set_cgpio_analog(self, ionum, value, sync=True):
|
|
241
|
+
assert ionum == 0 or ionum == 1, 'The value of parameter ionum can only be 0 or 1.'
|
|
242
|
+
if not sync and not self.version_is_ge(2, 4, 101):
|
|
243
|
+
logger.warning('The current firmware does not support sync to False. If necessary, please upgrade the firmware to 2.4.101 or later.')
|
|
244
|
+
if ionum == 0:
|
|
245
|
+
ret = self.arm_cmd.cgpio_set_analog1(value, sync=sync if self.version_is_ge(2, 4, 101) else None)
|
|
246
|
+
else:
|
|
247
|
+
ret = self.arm_cmd.cgpio_set_analog2(value, sync=sync if self.version_is_ge(2, 4, 101) else None)
|
|
248
|
+
self.log_api_info('API -> set_cgpio_analog(ionum={}, value={}) -> code={}'.format(ionum, value, ret[0]), code=ret[0])
|
|
249
|
+
return ret[0]
|
|
250
|
+
|
|
251
|
+
@xarm_is_connected(_type='set')
|
|
252
|
+
def set_cgpio_digital_input_function(self, ionum, fun):
|
|
253
|
+
assert isinstance(ionum, int) and 15 >= ionum >= 0
|
|
254
|
+
ret = self.arm_cmd.cgpio_set_infun(ionum, fun)
|
|
255
|
+
self.log_api_info('API -> set_cgpio_digital_input_function(ionum={}, fun={}) -> code={}'.format(ionum, fun, ret[0]), code=ret[0])
|
|
256
|
+
return ret[0]
|
|
257
|
+
|
|
258
|
+
@xarm_is_connected(_type='set')
|
|
259
|
+
def set_cgpio_digital_output_function(self, ionum, fun):
|
|
260
|
+
assert isinstance(ionum, int) and 15 >= ionum >= 0
|
|
261
|
+
ret = self.arm_cmd.cgpio_set_outfun(ionum, fun)
|
|
262
|
+
self.log_api_info('API -> set_cgpio_digital_output_function(ionum={}, fun={}) -> code={}'.format(ionum, fun, ret[0]), code=ret[0])
|
|
263
|
+
return ret[0]
|
|
264
|
+
|
|
265
|
+
@xarm_is_connected(_type='get')
|
|
266
|
+
def get_cgpio_state(self):
|
|
267
|
+
ret = self.arm_cmd.cgpio_get_state()
|
|
268
|
+
code, states = ret[0], ret[1:]
|
|
269
|
+
if not self._control_box_type_is_1300:
|
|
270
|
+
states[-1] = states[-1][:8]
|
|
271
|
+
states[-2] = states[-2][:8]
|
|
272
|
+
if code == 0 and states[0] == 0 and states[1] == 0:
|
|
273
|
+
self.cgpio_state['digital'] = [states[3] >> i & 0x0001 if states[10][i] in [0, 255] else 1 for i in range(len(states[10]))]
|
|
274
|
+
self.cgpio_state['analog'] = [states[6], states[7]]
|
|
275
|
+
# data = {
|
|
276
|
+
# 'state': ret[1],
|
|
277
|
+
# 'error_code': ret[2],
|
|
278
|
+
# 'digital': {
|
|
279
|
+
# 'functional': {
|
|
280
|
+
# 'input': [ret[3] >> i & 0x01 for i in range(8)],
|
|
281
|
+
# 'output': [ret[5] >> i & 0x01 for i in range(8)]
|
|
282
|
+
# },
|
|
283
|
+
# 'configuring': {
|
|
284
|
+
# 'input': [ret[4] >> i & 0x01 for i in range(8)],
|
|
285
|
+
# 'output': [ret[6] >> i & 0x01 for i in range(8)],
|
|
286
|
+
# }
|
|
287
|
+
# },
|
|
288
|
+
# 'analog': {
|
|
289
|
+
# 'input': [ret[7], ret[8]],
|
|
290
|
+
# 'output': [ret[9], ret[10]]
|
|
291
|
+
# },
|
|
292
|
+
# 'digital_fun': {
|
|
293
|
+
# 'input': ret[11],
|
|
294
|
+
# 'output': ret[12]
|
|
295
|
+
# }
|
|
296
|
+
# }
|
|
297
|
+
# import json
|
|
298
|
+
# # print(json.dumps(data, sort_keys=True, indent=4, skipkeys=True, separators=(',', ':'), ensure_ascii=False))
|
|
299
|
+
# print('cgpio_state:', ret[1])
|
|
300
|
+
# print('cgpio_err_code:', ret[2])
|
|
301
|
+
# print('cgpio_digital_input_fun_state:', bin(ret[3]))
|
|
302
|
+
# print('cgpio_digital_input_cfg_state:', bin(ret[4]))
|
|
303
|
+
# print('cgpio_digital_output_fun_state:', bin(ret[5]))
|
|
304
|
+
# print('cgpio_digital_output_cfg_state:', bin(ret[6]))
|
|
305
|
+
# print('cgpio_analog_1_input:', ret[7])
|
|
306
|
+
# print('cgpio_analog_2_input:', ret[8])
|
|
307
|
+
# print('cgpio_analog_1_output:', ret[9])
|
|
308
|
+
# print('cgpio_analog_2_output:', ret[10])
|
|
309
|
+
# print('cgpio_digital_input_fun:', ret[11])
|
|
310
|
+
# print('cgpio_digital_output_fun:', ret[12])
|
|
311
|
+
return code, states
|
|
312
|
+
|
|
313
|
+
@xarm_is_connected(_type='get')
|
|
314
|
+
def get_cgpio_li_state(self, Ci_Li, timeout=3, is_ci=True):
|
|
315
|
+
start_time = time.monotonic()
|
|
316
|
+
is_first = True
|
|
317
|
+
while is_first or time.monotonic() - start_time < timeout:
|
|
318
|
+
code = 0
|
|
319
|
+
is_first = False
|
|
320
|
+
if not self.connected or self.state == 4:
|
|
321
|
+
return False
|
|
322
|
+
codes, ret = self.get_cgpio_state()
|
|
323
|
+
digitals = [ret[3] >> i & 0x0001 if ret[10][i] in [0, 255] else 1 for i in
|
|
324
|
+
range(len(ret[10]))]
|
|
325
|
+
if codes == XCONF.UxbusState.ERR_CODE:
|
|
326
|
+
return False
|
|
327
|
+
if codes == 0:
|
|
328
|
+
for CI_num, CI in enumerate(Ci_Li):
|
|
329
|
+
if int(CI) != digitals[CI_num if is_ci else CI_num + 8]:
|
|
330
|
+
code = -1
|
|
331
|
+
break
|
|
332
|
+
if code == 0:
|
|
333
|
+
return True
|
|
334
|
+
time.sleep(0.1)
|
|
335
|
+
return False
|
|
336
|
+
|
|
337
|
+
@xarm_is_connected(_type='get')
|
|
338
|
+
def get_tgpio_li_state(self, Ti_Li, timeout=3):
|
|
339
|
+
start_time = time.monotonic()
|
|
340
|
+
is_first = True
|
|
341
|
+
while is_first or time.monotonic() - start_time < timeout:
|
|
342
|
+
code = 0
|
|
343
|
+
is_first = False
|
|
344
|
+
if not self.connected or self.state == 4:
|
|
345
|
+
return False
|
|
346
|
+
codes, ret = self.get_tgpio_digital()
|
|
347
|
+
if codes == XCONF.UxbusState.ERR_CODE:
|
|
348
|
+
return False
|
|
349
|
+
if codes == 0:
|
|
350
|
+
for TI_num, TI in enumerate(Ti_Li):
|
|
351
|
+
if int(TI) != ret[TI_num]:
|
|
352
|
+
code = -1
|
|
353
|
+
break
|
|
354
|
+
if code == 0:
|
|
355
|
+
return True
|
|
356
|
+
time.sleep(0.1)
|
|
357
|
+
return False
|
|
358
|
+
|
|
359
|
+
@xarm_wait_until_not_pause
|
|
360
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
361
|
+
@xarm_is_ready(_type='set')
|
|
362
|
+
@xarm_is_not_simulation_mode(ret=0)
|
|
363
|
+
def set_suction_cup(self, on, wait=True, timeout=3, delay_sec=None, sync=True, hardware_version=1):
|
|
364
|
+
if on:
|
|
365
|
+
code1 = self.set_tgpio_digital(ionum=0 if hardware_version == 1 else 3, value=1, delay_sec=delay_sec, sync=sync)
|
|
366
|
+
code2 = self.set_tgpio_digital(ionum=1 if hardware_version == 1 else 4, value=0, delay_sec=delay_sec, sync=sync)
|
|
367
|
+
else:
|
|
368
|
+
code1 = self.set_tgpio_digital(ionum=0 if hardware_version == 1 else 3, value=0, delay_sec=delay_sec, sync=sync)
|
|
369
|
+
code2 = self.set_tgpio_digital(ionum=1 if hardware_version == 1 else 4, value=1, delay_sec=delay_sec, sync=sync)
|
|
370
|
+
code = code1 if code2 == 0 else code2
|
|
371
|
+
if code == 0 and wait:
|
|
372
|
+
start = time.monotonic()
|
|
373
|
+
code = APIState.SUCTION_CUP_TOUT
|
|
374
|
+
if delay_sec is not None and delay_sec > 0:
|
|
375
|
+
timeout += delay_sec
|
|
376
|
+
while time.monotonic() - start < timeout:
|
|
377
|
+
ret = self.get_suction_cup(hardware_version=hardware_version)
|
|
378
|
+
if ret[0] == XCONF.UxbusState.ERR_CODE:
|
|
379
|
+
code = XCONF.UxbusState.ERR_CODE
|
|
380
|
+
break
|
|
381
|
+
if ret[0] == 0:
|
|
382
|
+
if on and ret[1] == 1:
|
|
383
|
+
code = 0
|
|
384
|
+
break
|
|
385
|
+
if not on and ret[1] == 0:
|
|
386
|
+
code = 0
|
|
387
|
+
break
|
|
388
|
+
if not self.connected or self.state == 4:
|
|
389
|
+
code = APIState.EMERGENCY_STOP
|
|
390
|
+
break
|
|
391
|
+
time.sleep(0.1)
|
|
392
|
+
self.log_api_info('API -> set_suction_cup(on={}, wait={}, delay_sec={}) -> code={}'.format(on, wait, delay_sec, code), code=code)
|
|
393
|
+
return code
|
|
394
|
+
|
|
395
|
+
@xarm_is_connected(_type='get')
|
|
396
|
+
def get_suction_cup(self, hardware_version=1):
|
|
397
|
+
return self.get_tgpio_digital(ionum=0 if hardware_version == 1 else 3)
|
|
398
|
+
|
|
399
|
+
@xarm_wait_until_not_pause
|
|
400
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
401
|
+
@xarm_is_ready(_type='set')
|
|
402
|
+
@xarm_is_not_simulation_mode(ret=0)
|
|
403
|
+
def set_tgpio_digital_with_xyz(self, ionum, value, xyz, fault_tolerance_radius):
|
|
404
|
+
assert isinstance(ionum, int) and (1 >= ionum >= 0 or 4 >= ionum >= 3)
|
|
405
|
+
assert fault_tolerance_radius >= 0, 'The value of parameter fault_tolerance_radius must be greater than or equal to 0.'
|
|
406
|
+
ret = self.arm_cmd.tgpio_position_set_digital(ionum - 1 if ionum >= 3 else ionum, value, xyz, fault_tolerance_radius)
|
|
407
|
+
self.log_api_info('API -> set_tgpio_digital_with_xyz(ionum={}, value={}, xyz={}, fault_tolerance_radius={}) -> code={}'.format(ionum, value, xyz, fault_tolerance_radius, ret[0]), code=ret[0])
|
|
408
|
+
return ret[0]
|
|
409
|
+
|
|
410
|
+
@xarm_wait_until_not_pause
|
|
411
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
412
|
+
@xarm_is_ready(_type='set')
|
|
413
|
+
@xarm_is_not_simulation_mode(ret=0)
|
|
414
|
+
def set_cgpio_digital_with_xyz(self, ionum, value, xyz, fault_tolerance_radius):
|
|
415
|
+
assert isinstance(ionum, int) and 15 >= ionum >= 0
|
|
416
|
+
assert fault_tolerance_radius >= 0, 'The value of parameter fault_tolerance_radius must be greater than or equal to 0.'
|
|
417
|
+
ret = self.arm_cmd.cgpio_position_set_digital(ionum, value, xyz, fault_tolerance_radius)
|
|
418
|
+
self.log_api_info('API -> set_cgpio_digital_with_xyz(ionum={}, value={}, xyz={}, fault_tolerance_radius={}) -> code={}'.format(ionum, value, xyz, fault_tolerance_radius, ret[0]), code=ret[0])
|
|
419
|
+
return ret[0]
|
|
420
|
+
|
|
421
|
+
@xarm_wait_until_not_pause
|
|
422
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
423
|
+
@xarm_is_ready(_type='set')
|
|
424
|
+
@xarm_is_not_simulation_mode(ret=0)
|
|
425
|
+
def set_cgpio_analog_with_xyz(self, ionum, value, xyz, fault_tolerance_radius):
|
|
426
|
+
assert ionum == 0 or ionum == 1, 'The value of parameter ionum can only be 0 or 1.'
|
|
427
|
+
assert fault_tolerance_radius >= 0, 'The value of parameter fault_tolerance_radius must be greater than or equal to 0.'
|
|
428
|
+
ret = self.arm_cmd.cgpio_position_set_analog(ionum, value, xyz, fault_tolerance_radius)
|
|
429
|
+
self.log_api_info('API -> set_cgpio_analog_with_xyz(ionum={}, value={}, xyz={}, fault_tolerance_radius={}) -> code={}'.format(ionum, value, xyz, fault_tolerance_radius, ret[0]), code=ret[0])
|
|
430
|
+
return ret[0]
|
|
431
|
+
|
|
432
|
+
@xarm_is_connected(_type='set')
|
|
433
|
+
def config_io_reset_when_stop(self, io_type, on_off):
|
|
434
|
+
ret = self.arm_cmd.config_io_stop_reset(io_type, int(on_off))
|
|
435
|
+
return ret[0]
|
|
436
|
+
|
|
437
|
+
@xarm_is_connected(_type='set')
|
|
438
|
+
@xarm_is_not_simulation_mode(ret=False)
|
|
439
|
+
def check_air_pump_state(self, state, timeout=3, hardware_version=1):
|
|
440
|
+
start_time = time.monotonic()
|
|
441
|
+
is_first = True
|
|
442
|
+
while is_first or time.monotonic() - start_time < timeout:
|
|
443
|
+
is_first = False
|
|
444
|
+
if not self.connected or self.state == 4:
|
|
445
|
+
return False
|
|
446
|
+
ret = self.get_suction_cup(hardware_version=hardware_version)
|
|
447
|
+
if ret[0] == XCONF.UxbusState.ERR_CODE:
|
|
448
|
+
return False
|
|
449
|
+
if ret[0] == 0:
|
|
450
|
+
if state and ret[1] == 1:
|
|
451
|
+
return True
|
|
452
|
+
if not state and ret[1] == 0:
|
|
453
|
+
return True
|
|
454
|
+
time.sleep(0.1)
|
|
455
|
+
return False
|
|
456
|
+
|
|
457
|
+
|
xarm/x3/grammar_async.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Software License Agreement (BSD License)
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2022, UFACTORY, Inc.
|
|
5
|
+
# All rights reserved.
|
|
6
|
+
#
|
|
7
|
+
# Author: Vinman <vinman.wen@ufactory.cc> <vinman.cub@gmail.com>
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
10
|
+
from ..core.utils.log import logger
|
|
11
|
+
|
|
12
|
+
class AsyncObject(object):
|
|
13
|
+
async def _asyncio_loop_func(self):
|
|
14
|
+
logger.debug('asyncio thread start ...')
|
|
15
|
+
while self.connected:
|
|
16
|
+
await asyncio.sleep(0.001)
|
|
17
|
+
logger.debug('asyncio thread exit ...')
|
|
18
|
+
|
|
19
|
+
@staticmethod
|
|
20
|
+
async def _async_run_callback(callback, msg):
|
|
21
|
+
await callback(msg)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Software License Agreement (BSD License)
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2022, UFACTORY, Inc.
|
|
5
|
+
# All rights reserved.
|
|
6
|
+
#
|
|
7
|
+
# Author: Vinman <vinman.wen@ufactory.cc> <vinman.cub@gmail.com>
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
10
|
+
from ..core.utils.log import logger
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CoroutineObject(object):
|
|
14
|
+
@asyncio.coroutine
|
|
15
|
+
def _asyncio_loop_func(self):
|
|
16
|
+
logger.debug('asyncio thread start ...')
|
|
17
|
+
while self.connected:
|
|
18
|
+
yield from asyncio.sleep(0.001)
|
|
19
|
+
logger.debug('asyncio thread exit ...')
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
@asyncio.coroutine
|
|
23
|
+
def _async_run_callback(callback, msg):
|
|
24
|
+
yield from callback(msg)
|