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/robotiq.py
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Software License Agreement (BSD License)
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2020, 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 .code import APIState
|
|
12
|
+
from .base import Base
|
|
13
|
+
from .decorator import xarm_is_connected, xarm_is_not_simulation_mode
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class RobotIQ(Base):
|
|
17
|
+
def __init__(self):
|
|
18
|
+
super(RobotIQ, self).__init__()
|
|
19
|
+
self.__robotiq_openmm = None
|
|
20
|
+
self.__robotiq_closemm = None
|
|
21
|
+
self.__robotiq_aCoef = None
|
|
22
|
+
self.__robotiq_bCoef = None
|
|
23
|
+
self._robotiq_status = {
|
|
24
|
+
'gOBJ': 0, # 1和2表示停止并抓取到物体,3表示停止但没有抓取到物体,0表示正在动也没有抓取到物体
|
|
25
|
+
'gSTA': 0, # 3表示激活完成
|
|
26
|
+
'gGTO': 0,
|
|
27
|
+
'gACT': 0,
|
|
28
|
+
'kFLT': 0,
|
|
29
|
+
'gFLT': 0, # 错误码
|
|
30
|
+
'gPR': 0, # 抓取器的目标位置
|
|
31
|
+
'gPO': 0, # 通过编码器获取抓取器的实际位置, 值介于0x00和0xFF之间, 0xFF为全闭合, 0x00为全张开
|
|
32
|
+
'gCU': 0, # 从电机驱动器上瞬时读电流, 值介于0x00和0xFF之间, 等效电流大约为=10 * value mA
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def robotiq_error_code(self):
|
|
37
|
+
return self.robotiq_status['gFLT']
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def robotiq_status(self):
|
|
41
|
+
return self._robotiq_status
|
|
42
|
+
|
|
43
|
+
def __robotiq_send_modbus(self, data_frame, min_res_len=0):
|
|
44
|
+
code = self.checkset_modbus_baud(self._default_robotiq_baud)
|
|
45
|
+
if code != 0:
|
|
46
|
+
return code, []
|
|
47
|
+
return self.getset_tgpio_modbus_data(data_frame, min_res_len=min_res_len, ignore_log=True)
|
|
48
|
+
|
|
49
|
+
@xarm_is_connected(_type='get')
|
|
50
|
+
def __robotiq_set(self, params):
|
|
51
|
+
data_frame = [0x09, 0x10, 0x03, 0xE8, 0x00, 0x03, len(params)]
|
|
52
|
+
data_frame.extend(params)
|
|
53
|
+
return self.__robotiq_send_modbus(data_frame, 6)
|
|
54
|
+
|
|
55
|
+
@xarm_is_connected(_type='get')
|
|
56
|
+
def __robotiq_get(self, params):
|
|
57
|
+
data_frame = [0x09, 0x03]
|
|
58
|
+
data_frame.extend(params)
|
|
59
|
+
code, ret = self.__robotiq_send_modbus(data_frame, 3 + 2 * params[-1])
|
|
60
|
+
if code == 0 and len(ret) >= 5:
|
|
61
|
+
gripper_status_reg = ret[3]
|
|
62
|
+
self._robotiq_status['gOBJ'] = (gripper_status_reg & 0xC0) >> 6
|
|
63
|
+
self._robotiq_status['gSTA'] = (gripper_status_reg & 0x30) >> 4
|
|
64
|
+
self._robotiq_status['gGTO'] = (gripper_status_reg & 0x08) >> 3
|
|
65
|
+
self._robotiq_status['gACT'] = gripper_status_reg & 0x01
|
|
66
|
+
if len(ret) >= 7:
|
|
67
|
+
fault_status_reg = ret[5]
|
|
68
|
+
self._robotiq_status['kFLT'] = (fault_status_reg & 0xF0) >> 4
|
|
69
|
+
self._robotiq_status['gFLT'] = fault_status_reg & 0x0F
|
|
70
|
+
self._robotiq_status['gPR'] = ret[6]
|
|
71
|
+
if len(ret) >= 9:
|
|
72
|
+
self._robotiq_status['gPO'] = ret[7]
|
|
73
|
+
self._robotiq_status['gCU'] = ret[8]
|
|
74
|
+
if self._robotiq_status['gSTA'] == 3 and (self._robotiq_status['gFLT'] == 0 or self._robotiq_status['gFLT'] == 9):
|
|
75
|
+
self.robotiq_is_activated = True
|
|
76
|
+
else:
|
|
77
|
+
self.robotiq_is_activated = False
|
|
78
|
+
return code, ret
|
|
79
|
+
|
|
80
|
+
@xarm_is_connected(_type='get')
|
|
81
|
+
@xarm_is_not_simulation_mode(ret=(0, 0))
|
|
82
|
+
def robotiq_reset(self):
|
|
83
|
+
params = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
|
|
84
|
+
code, ret = self.__robotiq_set(params)
|
|
85
|
+
self.log_api_info('API -> robotiq_reset -> code={}, response={}'.format(code, ret), code=code)
|
|
86
|
+
return code, ret
|
|
87
|
+
|
|
88
|
+
@xarm_is_connected(_type='get')
|
|
89
|
+
@xarm_is_not_simulation_mode(ret=(0, 0))
|
|
90
|
+
def robotiq_set_activate(self, wait=True, timeout=3):
|
|
91
|
+
params = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00]
|
|
92
|
+
code, ret = self.__robotiq_set(params)
|
|
93
|
+
if wait and code == 0:
|
|
94
|
+
code = self.robotiq_wait_activation_completed(timeout)
|
|
95
|
+
self.log_api_info('API -> robotiq_set_activate ->code={}, response={}'.format(code, ret), code=code)
|
|
96
|
+
if code == 0:
|
|
97
|
+
self.robotiq_is_activated = True
|
|
98
|
+
return code, ret
|
|
99
|
+
|
|
100
|
+
@xarm_is_connected(_type='get')
|
|
101
|
+
def robotiq_set_position(self, pos, speed=0xFF, force=0xFF, wait=True, timeout=5, **kwargs):
|
|
102
|
+
if kwargs.get('wait_motion', True):
|
|
103
|
+
has_error = self.error_code != 0
|
|
104
|
+
is_stop = self.is_stop
|
|
105
|
+
code = self.wait_move()
|
|
106
|
+
if not (code == 0 or (is_stop and code == APIState.EMERGENCY_STOP)
|
|
107
|
+
or (has_error and code == APIState.HAS_ERROR)):
|
|
108
|
+
return code, 0
|
|
109
|
+
if self.check_is_simulation_robot():
|
|
110
|
+
return 0, 0
|
|
111
|
+
if kwargs.get('auto_enable') and not self.robotiq_is_activated:
|
|
112
|
+
self.robotiq_reset()
|
|
113
|
+
self.robotiq_set_activate(wait=True)
|
|
114
|
+
params = [0x09, 0x00, 0x00, pos, speed, force]
|
|
115
|
+
code, ret = self.__robotiq_set(params)
|
|
116
|
+
if wait and code == 0:
|
|
117
|
+
code = self.robotiq_wait_motion_completed(timeout, **kwargs)
|
|
118
|
+
self.log_api_info('API -> robotiq_set_position ->code={}, response={}'.format(code, ret), code=code)
|
|
119
|
+
return code, ret
|
|
120
|
+
|
|
121
|
+
def robotiq_open(self, speed=0xFF, force=0xFF, wait=True, timeout=5, **kwargs):
|
|
122
|
+
return self.robotiq_set_position(0x00, speed=speed, force=force, wait=wait, timeout=timeout, **kwargs)
|
|
123
|
+
|
|
124
|
+
def robotiq_close(self, speed=0xFF, force=0xFF, wait=True, timeout=5, **kwargs):
|
|
125
|
+
return self.robotiq_set_position(0xFF, speed=speed, force=force, wait=wait, timeout=timeout, **kwargs)
|
|
126
|
+
|
|
127
|
+
@xarm_is_connected(_type='get')
|
|
128
|
+
@xarm_is_not_simulation_mode(ret=(0, 0))
|
|
129
|
+
def robotiq_get_status(self, number_of_registers=3):
|
|
130
|
+
number_of_registers = 3 if number_of_registers not in [1, 2, 3] else number_of_registers
|
|
131
|
+
params = [0x07, 0xD0, 0x00, number_of_registers]
|
|
132
|
+
# params = [0x07, 0xD0, 0x00, 0x01]
|
|
133
|
+
# params = [0x07, 0xD0, 0x00, 0x03]
|
|
134
|
+
return self.__robotiq_get(params)
|
|
135
|
+
|
|
136
|
+
def robotiq_wait_activation_completed(self, timeout=3):
|
|
137
|
+
failed_cnt = 0
|
|
138
|
+
expired = time.monotonic() + timeout if timeout is not None and timeout > 0 else 0
|
|
139
|
+
code = APIState.WAIT_FINISH_TIMEOUT
|
|
140
|
+
while expired == 0 or time.monotonic() < expired:
|
|
141
|
+
_, ret = self.robotiq_get_status(number_of_registers=3)
|
|
142
|
+
failed_cnt = 0 if _ == 0 else failed_cnt + 1
|
|
143
|
+
if _ == 0:
|
|
144
|
+
gFLT = self._robotiq_status['gFLT']
|
|
145
|
+
gSTA = self._robotiq_status['gSTA']
|
|
146
|
+
code = APIState.END_EFFECTOR_HAS_FAULT if gFLT != 0 and not (gFLT == 5 and gSTA == 1) \
|
|
147
|
+
else 0 if gSTA == 3 else code
|
|
148
|
+
else:
|
|
149
|
+
code = APIState.NOT_CONNECTED if _ == APIState.NOT_CONNECTED else APIState.CHECK_FAILED if failed_cnt > 10 else code
|
|
150
|
+
if code != APIState.WAIT_FINISH_TIMEOUT:
|
|
151
|
+
break
|
|
152
|
+
time.sleep(0.05)
|
|
153
|
+
return code
|
|
154
|
+
|
|
155
|
+
def robotiq_wait_motion_completed(self, timeout=5, **kwargs):
|
|
156
|
+
failed_cnt = 0
|
|
157
|
+
expired = time.monotonic() + timeout if timeout is not None and timeout > 0 else 0
|
|
158
|
+
code = APIState.WAIT_FINISH_TIMEOUT
|
|
159
|
+
check_detected = kwargs.get('check_detected', False)
|
|
160
|
+
while expired == 0 or time.monotonic() < expired:
|
|
161
|
+
_, ret = self.robotiq_get_status(number_of_registers=3)
|
|
162
|
+
failed_cnt = 0 if _ == 0 else failed_cnt + 1
|
|
163
|
+
if _ == 0:
|
|
164
|
+
gFLT = self._robotiq_status['gFLT']
|
|
165
|
+
gSTA = self._robotiq_status['gSTA']
|
|
166
|
+
gOBJ = self._robotiq_status['gOBJ']
|
|
167
|
+
code = APIState.END_EFFECTOR_HAS_FAULT if gFLT != 0 and not (gFLT == 5 and gSTA == 1) \
|
|
168
|
+
else 0 if (check_detected and (gOBJ == 1 or gOBJ == 2)) or (gOBJ == 1 or gOBJ == 2 or gOBJ == 3) \
|
|
169
|
+
else code
|
|
170
|
+
else:
|
|
171
|
+
code = APIState.NOT_CONNECTED if _ == APIState.NOT_CONNECTED else APIState.CHECK_FAILED if failed_cnt > 10 else code
|
|
172
|
+
if code != APIState.WAIT_FINISH_TIMEOUT:
|
|
173
|
+
break
|
|
174
|
+
time.sleep(0.05)
|
|
175
|
+
if self.robotiq_error_code != 0:
|
|
176
|
+
print('ROBOTIQ Gripper ErrorCode: {}'.format(self.robotiq_error_code))
|
|
177
|
+
if code == 0 and not self.robotiq_is_activated:
|
|
178
|
+
code = APIState.END_EFFECTOR_NOT_ENABLED
|
|
179
|
+
return code
|
|
180
|
+
|
|
181
|
+
@xarm_is_connected(_type='set')
|
|
182
|
+
@xarm_is_not_simulation_mode(ret=False)
|
|
183
|
+
def check_robotiq_is_catch(self, timeout=5):
|
|
184
|
+
return self.robotiq_wait_motion_completed(timeout=timeout, check_detected=True) == 0
|
|
185
|
+
|
|
186
|
+
def robotiq_calibrate_mm(self, closemm, openmm):
|
|
187
|
+
ret = self.robotiq_open(wait=True)
|
|
188
|
+
if ret[0] == 0:
|
|
189
|
+
open_bit = self._robotiq_status['gPO']
|
|
190
|
+
ret = self.robotiq_close(wait=True)
|
|
191
|
+
if ret[0] == 0:
|
|
192
|
+
close_bit = self._robotiq_status['gPO']
|
|
193
|
+
self.__robotiq_aCoef = (closemm - openmm) / (close_bit - open_bit)
|
|
194
|
+
self.__robotiq_bCoef = (openmm * close_bit - closemm * open_bit) / (close_bit - open_bit)
|
|
195
|
+
self.__robotiq_closemm = closemm
|
|
196
|
+
self.__robotiq_openmm = openmm
|
|
197
|
+
return 0
|
|
198
|
+
return ret[0]
|
|
199
|
+
|
|
200
|
+
def robotiq_set_position_mm(self, pos_mm, speed=0xFF, force=0xFF, wait=False, timeout=5, check_detected=False):
|
|
201
|
+
if self.__robotiq_openmm is None or self.__robotiq_closemm is None:
|
|
202
|
+
print('You have to calibrate the gripper before using the function robotiq_set_position_mm()')
|
|
203
|
+
elif pos_mm > self.__robotiq_openmm:
|
|
204
|
+
print("The maximum opening is {}".format(self.__robotiq_openmm))
|
|
205
|
+
else:
|
|
206
|
+
pos = int(self.__robotiq_mm_to_bit(pos_mm))
|
|
207
|
+
return self.robotiq_set_position(pos, speed=speed, force=force, wait=wait, timeout=timeout, check_detected=check_detected)
|
|
208
|
+
|
|
209
|
+
def __robotiq_mm_to_bit(self, mm):
|
|
210
|
+
if self.__robotiq_aCoef is None or self.__robotiq_bCoef is None:
|
|
211
|
+
print('You have to calibrate the gripper before using the function robotiq_mm_to_bit()')
|
|
212
|
+
else:
|
|
213
|
+
return (mm - self.__robotiq_bCoef) / self.__robotiq_aCoef
|
|
214
|
+
|
|
215
|
+
def __robotiq_bit_to_mm(self, bit):
|
|
216
|
+
if self.__robotiq_aCoef is None or self.__robotiq_bCoef is None:
|
|
217
|
+
print('You have to calibrate the gripper before using the function robotiq_bit_to_mm()')
|
|
218
|
+
else:
|
|
219
|
+
return self.__robotiq_aCoef * bit + self.__robotiq_bCoef
|
|
220
|
+
|