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/xarm.py
ADDED
|
@@ -0,0 +1,1928 @@
|
|
|
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 os
|
|
10
|
+
import re
|
|
11
|
+
import math
|
|
12
|
+
import sys
|
|
13
|
+
import time
|
|
14
|
+
import uuid
|
|
15
|
+
import socket
|
|
16
|
+
import warnings
|
|
17
|
+
from collections.abc import Iterable
|
|
18
|
+
from ..core.config.x_config import XCONF
|
|
19
|
+
from ..core.utils.log import logger
|
|
20
|
+
from .base import Base
|
|
21
|
+
from .gripper import Gripper
|
|
22
|
+
from .track import Track
|
|
23
|
+
from .base_board import BaseBoard
|
|
24
|
+
from .servo import Servo
|
|
25
|
+
from .record import Record
|
|
26
|
+
from .robotiq import RobotIQ
|
|
27
|
+
from .ft_sensor import FtSensor
|
|
28
|
+
from .modbus_tcp import ModbusTcp
|
|
29
|
+
from .parse import GcodeParser
|
|
30
|
+
from .code import APIState
|
|
31
|
+
from .decorator import xarm_is_connected, xarm_is_ready, xarm_wait_until_not_pause, xarm_wait_until_cmdnum_lt_max
|
|
32
|
+
from .utils import to_radian
|
|
33
|
+
try:
|
|
34
|
+
# from ..tools.blockly_tool import BlocklyTool
|
|
35
|
+
from ..tools.blockly import BlocklyTool
|
|
36
|
+
except:
|
|
37
|
+
print('import BlocklyTool module failed')
|
|
38
|
+
BlocklyTool = None
|
|
39
|
+
|
|
40
|
+
gcode_p = GcodeParser()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class XArm(Gripper, Servo, Record, RobotIQ, BaseBoard, Track, FtSensor, ModbusTcp):
|
|
44
|
+
|
|
45
|
+
def __init__(self, port=None, is_radian=False, do_not_open=False, instance=None, **kwargs):
|
|
46
|
+
super(XArm, self).__init__()
|
|
47
|
+
kwargs['init'] = True
|
|
48
|
+
self._api_instance = instance
|
|
49
|
+
Base.__init__(self, port, is_radian, do_not_open, **kwargs)
|
|
50
|
+
|
|
51
|
+
def _is_out_of_tcp_range(self, value, i):
|
|
52
|
+
if not self._check_tcp_limit or self._stream_type != 'socket' or not self._enable_report or value == math.inf:
|
|
53
|
+
return False
|
|
54
|
+
tcp_range = XCONF.Robot.TCP_LIMITS.get(self.axis).get(self.device_type, [])
|
|
55
|
+
if 2 < i < len(tcp_range): # only limit rotate
|
|
56
|
+
limit = list(tcp_range[i])
|
|
57
|
+
limit[0] += self._position_offset[i]
|
|
58
|
+
limit[1] += self._position_offset[i]
|
|
59
|
+
limit[0] += self._world_offset[i]
|
|
60
|
+
limit[1] += self._world_offset[i]
|
|
61
|
+
if limit[0] == limit[1]:
|
|
62
|
+
return False
|
|
63
|
+
if value < limit[0] - math.radians(0.1) or value > limit[1] + math.radians(0.1):
|
|
64
|
+
self.log_api_info('API -> set_position -> out_of_tcp_range -> code={}, i={} value={}'.format(APIState.OUT_OF_RANGE, i, value), code=APIState.OUT_OF_RANGE)
|
|
65
|
+
return True
|
|
66
|
+
return False
|
|
67
|
+
|
|
68
|
+
def _is_out_of_joint_range(self, angle, i):
|
|
69
|
+
if not self._check_joint_limit or self._stream_type != 'socket' or not self._enable_report or angle == math.inf:
|
|
70
|
+
return False
|
|
71
|
+
device_type = int('{}1305'.format(self.axis)) if self.sn and int(self.sn[2:6]) >= 1305 and int(self.sn[2:6]) < 8500 else self.device_type
|
|
72
|
+
joint_limit = XCONF.Robot.JOINT_LIMITS.get(self.axis).get(device_type, [])
|
|
73
|
+
if i < len(joint_limit):
|
|
74
|
+
angle_range = joint_limit[i]
|
|
75
|
+
if angle < angle_range[0] - math.radians(0.1) or angle > angle_range[1] + math.radians(0.1):
|
|
76
|
+
self.log_api_info('API -> set_servo_angle -> out_of_joint_range -> code={}, i={} value={}'.format(APIState.OUT_OF_RANGE, i, angle), code=APIState.OUT_OF_RANGE)
|
|
77
|
+
return True
|
|
78
|
+
return False
|
|
79
|
+
|
|
80
|
+
def __wait_sync(self):
|
|
81
|
+
while not self._is_sync or self._need_sync:
|
|
82
|
+
if not self.connected:
|
|
83
|
+
return APIState.NOT_CONNECTED
|
|
84
|
+
# elif self.has_error:
|
|
85
|
+
# return APIState.HAS_ERROR
|
|
86
|
+
# elif self.is_stop:
|
|
87
|
+
# return APIState.NOT_READY
|
|
88
|
+
if self.has_error:
|
|
89
|
+
_, err_warn = self.get_err_warn_code()
|
|
90
|
+
if err_warn[0] != 0:
|
|
91
|
+
return APIState.HAS_ERROR
|
|
92
|
+
if self.is_stop:
|
|
93
|
+
_, state = self.get_state()
|
|
94
|
+
if state >= 4:
|
|
95
|
+
return APIState.NOT_READY
|
|
96
|
+
time.sleep(0.05)
|
|
97
|
+
return 0
|
|
98
|
+
|
|
99
|
+
def __update_tcp_motion_params(self, speed, acc, mvtime, pose=None):
|
|
100
|
+
self._last_tcp_speed = speed
|
|
101
|
+
self._last_tcp_acc = acc
|
|
102
|
+
self._mvtime = mvtime
|
|
103
|
+
if pose is not None:
|
|
104
|
+
self._last_position = pose.copy()
|
|
105
|
+
|
|
106
|
+
def __update_joint_motion_params(self, speed, acc, mvtime, angles=None):
|
|
107
|
+
self._last_joint_speed = speed
|
|
108
|
+
self._last_joint_acc = acc
|
|
109
|
+
self._mvtime = mvtime
|
|
110
|
+
if angles is not None:
|
|
111
|
+
self._last_angles = angles.copy()
|
|
112
|
+
|
|
113
|
+
def __get_tcp_motion_params(self, speed=None, mvacc=None, mvtime=None, **kwargs):
|
|
114
|
+
speed = speed if speed is not None else kwargs.get('mvvelo', self._last_tcp_speed)
|
|
115
|
+
# spd = self._last_tcp_speed if speed is None else min(max(float(speed), self._min_tcp_speed), self._max_tcp_speed)
|
|
116
|
+
# acc = self._last_tcp_acc if mvacc is None else min(max(float(mvacc), self._min_tcp_acc), self._max_tcp_acc)
|
|
117
|
+
spd = self._last_tcp_speed if speed is None else min(max(float(speed), self._min_tcp_speed), 1000)
|
|
118
|
+
acc = self._last_tcp_acc if mvacc is None else min(max(float(mvacc), self._min_tcp_acc), 50000)
|
|
119
|
+
mvt = self._mvtime if mvtime is None else mvtime
|
|
120
|
+
return spd, acc, mvt
|
|
121
|
+
|
|
122
|
+
def __get_joint_motion_params(self, speed=None, mvacc=None, mvtime=None, is_radian=None, **kwargs):
|
|
123
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
124
|
+
speed = speed if speed is not None else kwargs.get('mvvelo', None)
|
|
125
|
+
speed = self._last_joint_speed if speed is None else to_radian(speed, is_radian)
|
|
126
|
+
mvacc = self._last_joint_acc if mvacc is None else to_radian(mvacc, is_radian)
|
|
127
|
+
# spd = min(max(float(speed), self._min_joint_speed), self._max_joint_speed)
|
|
128
|
+
# acc = min(max(float(mvacc), self._min_joint_acc), self._max_joint_acc)
|
|
129
|
+
spd = min(max(float(speed), self._min_joint_speed), math.pi)
|
|
130
|
+
acc = min(max(float(mvacc), self._min_joint_acc), 20)
|
|
131
|
+
mvt = self._mvtime if mvtime is None else mvtime
|
|
132
|
+
return spd, acc, mvt
|
|
133
|
+
|
|
134
|
+
def _set_position_absolute(self, x=None, y=None, z=None, roll=None, pitch=None, yaw=None, radius=None,
|
|
135
|
+
speed=None, mvacc=None, mvtime=None, is_radian=None, wait=False, timeout=None, **kwargs):
|
|
136
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
137
|
+
only_check_type = kwargs.get('only_check_type', self._only_check_type)
|
|
138
|
+
tcp_pos = [
|
|
139
|
+
(math.inf if self.version_is_ge(2, 4, 101) else self._last_position[0]) if x is None else float(x),
|
|
140
|
+
(math.inf if self.version_is_ge(2, 4, 101) else self._last_position[1]) if y is None else float(y),
|
|
141
|
+
(math.inf if self.version_is_ge(2, 4, 101) else self._last_position[2]) if z is None else float(z),
|
|
142
|
+
(math.inf if self.version_is_ge(2, 4, 101) else self._last_position[3]) if roll is None else to_radian(roll, is_radian),
|
|
143
|
+
(math.inf if self.version_is_ge(2, 4, 101) else self._last_position[4]) if pitch is None else to_radian(pitch, is_radian),
|
|
144
|
+
(math.inf if self.version_is_ge(2, 4, 101) else self._last_position[5]) if yaw is None else to_radian(yaw, is_radian),
|
|
145
|
+
]
|
|
146
|
+
motion_type = kwargs.get('motion_type', False)
|
|
147
|
+
for i in range(3):
|
|
148
|
+
if self._is_out_of_tcp_range(tcp_pos[i+3], i + 3):
|
|
149
|
+
return APIState.OUT_OF_RANGE
|
|
150
|
+
if kwargs.get('check', False):
|
|
151
|
+
_, limit = self.is_tcp_limit(tcp_pos, True)
|
|
152
|
+
if _ == 0 and limit is True:
|
|
153
|
+
return APIState.TCP_LIMIT
|
|
154
|
+
self._has_motion_cmd = True
|
|
155
|
+
spd, acc, mvt = self.__get_tcp_motion_params(speed, mvacc, mvtime, **kwargs)
|
|
156
|
+
radius = radius if radius is not None else -1
|
|
157
|
+
feedback_key, studio_wait = self._gen_feedback_key(wait, **kwargs)
|
|
158
|
+
if self.version_is_ge(1, 11, 100) or kwargs.get('debug', False):
|
|
159
|
+
ret = self.arm_cmd.move_line_common(tcp_pos, spd, acc, mvt, radius, coord=0, is_axis_angle=False, only_check_type=only_check_type, motion_type=motion_type, feedback_key=feedback_key)
|
|
160
|
+
else:
|
|
161
|
+
if radius >= 0:
|
|
162
|
+
ret = self.arm_cmd.move_lineb(tcp_pos, spd, acc, mvt, radius, only_check_type, motion_type=motion_type)
|
|
163
|
+
else:
|
|
164
|
+
ret = self.arm_cmd.move_line(tcp_pos, spd, acc, mvt, only_check_type, motion_type=motion_type)
|
|
165
|
+
trans_id = self._get_feedback_transid(feedback_key, studio_wait, kwargs.get('is_pop', True))
|
|
166
|
+
ret[0] = self._check_code(ret[0], is_move_cmd=True)
|
|
167
|
+
self.log_api_info('API -> set_position -> code={}, pos={}, radius={}, velo={}, acc={}'.format(
|
|
168
|
+
ret[0], tcp_pos, radius, spd, acc), code=ret[0])
|
|
169
|
+
self._is_set_move = True
|
|
170
|
+
self._only_check_result = 0
|
|
171
|
+
if only_check_type > 0 and ret[0] == 0:
|
|
172
|
+
self._only_check_result = ret[3]
|
|
173
|
+
return APIState.HAS_ERROR if ret[3] != 0 else ret[0]
|
|
174
|
+
if only_check_type <= 0 and wait and ret[0] == 0:
|
|
175
|
+
code = self.wait_move(timeout, trans_id=trans_id)
|
|
176
|
+
self.__update_tcp_motion_params(spd, acc, mvt)
|
|
177
|
+
self._sync()
|
|
178
|
+
return code
|
|
179
|
+
if only_check_type <= 0 and (ret[0] >= 0 or self.get_is_moving()):
|
|
180
|
+
self.__update_tcp_motion_params(spd, acc, mvt, tcp_pos)
|
|
181
|
+
return ret[0]
|
|
182
|
+
|
|
183
|
+
def _set_position_relative(self, x=None, y=None, z=None, roll=None, pitch=None, yaw=None, radius=None,
|
|
184
|
+
speed=None, mvacc=None, mvtime=None, is_radian=None, wait=False, timeout=None, **kwargs):
|
|
185
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
186
|
+
only_check_type = kwargs.get('only_check_type', self._only_check_type)
|
|
187
|
+
motion_type = kwargs.get('motion_type', False)
|
|
188
|
+
if self.version_is_ge(1, 8, 100):
|
|
189
|
+
# use relative api
|
|
190
|
+
tcp_pos = [
|
|
191
|
+
0 if x is None else float(x),
|
|
192
|
+
0 if y is None else float(y),
|
|
193
|
+
0 if z is None else float(z),
|
|
194
|
+
0 if roll is None else to_radian(roll, is_radian),
|
|
195
|
+
0 if pitch is None else to_radian(pitch, is_radian),
|
|
196
|
+
0 if yaw is None else to_radian(yaw, is_radian),
|
|
197
|
+
]
|
|
198
|
+
self._has_motion_cmd = True
|
|
199
|
+
spd, acc, mvt = self.__get_tcp_motion_params(speed, mvacc, mvtime, **kwargs)
|
|
200
|
+
radius = radius if radius is not None else -1
|
|
201
|
+
feedback_key, studio_wait = self._gen_feedback_key(wait, **kwargs)
|
|
202
|
+
ret = self.arm_cmd.move_relative(tcp_pos, spd, acc, mvt, radius, False, False, only_check_type, motion_type=motion_type, feedback_key=feedback_key)
|
|
203
|
+
trans_id = self._get_feedback_transid(feedback_key, studio_wait, kwargs.get('is_pop', True))
|
|
204
|
+
ret[0] = self._check_code(ret[0], is_move_cmd=True)
|
|
205
|
+
self.log_api_info('API -> set_relative_position -> code={}, pos={}, radius={}, velo={}, acc={}'.format(
|
|
206
|
+
ret[0], tcp_pos, radius, spd, acc), code=ret[0])
|
|
207
|
+
self._is_set_move = True
|
|
208
|
+
self._only_check_result = 0
|
|
209
|
+
if only_check_type > 0 and ret[0] == 0:
|
|
210
|
+
self._only_check_result = ret[3]
|
|
211
|
+
return APIState.HAS_ERROR if ret[3] != 0 else ret[0]
|
|
212
|
+
if only_check_type <= 0 and wait and ret[0] == 0:
|
|
213
|
+
code = self.wait_move(timeout, trans_id=trans_id)
|
|
214
|
+
self.__update_tcp_motion_params(spd, acc, mvt)
|
|
215
|
+
self._sync()
|
|
216
|
+
return code
|
|
217
|
+
if only_check_type <= 0 and (ret[0] >= 0 or self.get_is_moving()):
|
|
218
|
+
self.__update_tcp_motion_params(spd, acc, mvt)
|
|
219
|
+
return ret[0]
|
|
220
|
+
else:
|
|
221
|
+
# use absolute api
|
|
222
|
+
tcp_pos = [
|
|
223
|
+
self._last_position[0] if x is None else (self._last_position[0] + float(x)),
|
|
224
|
+
self._last_position[1] if y is None else (self._last_position[1] + float(y)),
|
|
225
|
+
self._last_position[2] if z is None else (self._last_position[2] + float(z)),
|
|
226
|
+
self._last_position[3] if roll is None else (self._last_position[3] + to_radian(roll, is_radian)),
|
|
227
|
+
self._last_position[4] if pitch is None else (self._last_position[4] + to_radian(pitch, is_radian)),
|
|
228
|
+
self._last_position[5] if yaw is None else (self._last_position[5] + to_radian(yaw, is_radian)),
|
|
229
|
+
]
|
|
230
|
+
return self._set_position_absolute(*tcp_pos, radius=radius, speed=speed, mvacc=mvacc, mvtime=mvtime,
|
|
231
|
+
is_radian=True, wait=wait, timeout=timeout, **kwargs)
|
|
232
|
+
|
|
233
|
+
@xarm_wait_until_not_pause
|
|
234
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
235
|
+
@xarm_is_ready(_type='set')
|
|
236
|
+
def set_position(self, x=None, y=None, z=None, roll=None, pitch=None, yaw=None, radius=None,
|
|
237
|
+
speed=None, mvacc=None, mvtime=None, relative=False, is_radian=None,
|
|
238
|
+
wait=False, timeout=None, **kwargs):
|
|
239
|
+
only_check_type = kwargs.get('only_check_type', self._only_check_type)
|
|
240
|
+
if only_check_type > 0 and wait:
|
|
241
|
+
code = self.wait_move(timeout=timeout)
|
|
242
|
+
if code != 0:
|
|
243
|
+
return code
|
|
244
|
+
code = self.__wait_sync()
|
|
245
|
+
if code != 0:
|
|
246
|
+
return code
|
|
247
|
+
if relative:
|
|
248
|
+
return self._set_position_relative(x=x, y=y, z=z, roll=roll, pitch=pitch, yaw=yaw, radius=radius,
|
|
249
|
+
speed=speed, mvacc=mvacc, mvtime=mvtime, is_radian=is_radian,
|
|
250
|
+
wait=wait, timeout=timeout, **kwargs)
|
|
251
|
+
else:
|
|
252
|
+
return self._set_position_absolute(x=x, y=y, z=z, roll=roll, pitch=pitch, yaw=yaw, radius=radius,
|
|
253
|
+
speed=speed, mvacc=mvacc, mvtime=mvtime, is_radian=is_radian,
|
|
254
|
+
wait=wait, timeout=timeout, **kwargs)
|
|
255
|
+
|
|
256
|
+
@xarm_wait_until_not_pause
|
|
257
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
258
|
+
@xarm_is_ready(_type='set')
|
|
259
|
+
def set_tool_position(self, x=0, y=0, z=0, roll=0, pitch=0, yaw=0,
|
|
260
|
+
speed=None, mvacc=None, mvtime=None, is_radian=None,
|
|
261
|
+
wait=False, timeout=None, radius=None, **kwargs):
|
|
262
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
263
|
+
only_check_type = kwargs.get('only_check_type', self._only_check_type)
|
|
264
|
+
if only_check_type > 0 and wait:
|
|
265
|
+
code = self.wait_move(timeout=timeout)
|
|
266
|
+
if code != 0:
|
|
267
|
+
return code
|
|
268
|
+
tcp_pos = [
|
|
269
|
+
x, y, z,
|
|
270
|
+
to_radian(roll, is_radian),
|
|
271
|
+
to_radian(pitch, is_radian),
|
|
272
|
+
to_radian(yaw, is_radian)
|
|
273
|
+
]
|
|
274
|
+
spd, acc, mvt = self.__get_tcp_motion_params(speed, mvacc, mvtime, **kwargs)
|
|
275
|
+
self._has_motion_cmd = True
|
|
276
|
+
motion_type = kwargs.get('motion_type', False)
|
|
277
|
+
radius = radius if radius is not None else -1
|
|
278
|
+
feedback_key, studio_wait = self._gen_feedback_key(wait, **kwargs)
|
|
279
|
+
|
|
280
|
+
if self.version_is_ge(1, 11, 100) or kwargs.get('debug', False):
|
|
281
|
+
ret = self.arm_cmd.move_line_common(tcp_pos, spd, acc, mvt, radius, coord=1, is_axis_angle=False, only_check_type=only_check_type, motion_type=motion_type, feedback_key=feedback_key)
|
|
282
|
+
else:
|
|
283
|
+
ret = self.arm_cmd.move_line_tool(tcp_pos, spd, acc, mvt, only_check_type, motion_type=motion_type)
|
|
284
|
+
trans_id = self._get_feedback_transid(feedback_key, studio_wait, kwargs.get('is_pop', True))
|
|
285
|
+
ret[0] = self._check_code(ret[0], is_move_cmd=True)
|
|
286
|
+
self.log_api_info('API -> set_tool_position -> code={}, pos={}, velo={}, acc={}'.format(
|
|
287
|
+
ret[0], tcp_pos, spd, acc), code=ret[0])
|
|
288
|
+
self._is_set_move = True
|
|
289
|
+
self._only_check_result = 0
|
|
290
|
+
if only_check_type > 0 and ret[0] == 0:
|
|
291
|
+
self._only_check_result = ret[3]
|
|
292
|
+
return APIState.HAS_ERROR if ret[3] != 0 else ret[0]
|
|
293
|
+
if only_check_type <= 0 and wait and ret[0] == 0:
|
|
294
|
+
code = self.wait_move(timeout, trans_id=trans_id)
|
|
295
|
+
self.__update_tcp_motion_params(spd, acc, mvt)
|
|
296
|
+
self._sync()
|
|
297
|
+
return code
|
|
298
|
+
if only_check_type <= 0 and (ret[0] >= 0 or self.get_is_moving()):
|
|
299
|
+
self.__update_tcp_motion_params(spd, acc, mvt)
|
|
300
|
+
return ret[0]
|
|
301
|
+
|
|
302
|
+
@xarm_wait_until_not_pause
|
|
303
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
304
|
+
@xarm_is_ready(_type='set')
|
|
305
|
+
def set_position_aa(self, mvpose, speed=None, mvacc=None, mvtime=None,
|
|
306
|
+
is_radian=None, is_tool_coord=False, relative=False,
|
|
307
|
+
wait=False, timeout=None, radius=None, **kwargs):
|
|
308
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
309
|
+
only_check_type = kwargs.get('only_check_type', self._only_check_type)
|
|
310
|
+
if only_check_type > 0 and wait:
|
|
311
|
+
code = self.wait_move(timeout=timeout)
|
|
312
|
+
if code != 0:
|
|
313
|
+
return code
|
|
314
|
+
tcp_pos = [to_radian(mvpose[i], is_radian or i <= 2) for i in range(6)]
|
|
315
|
+
spd, acc, mvt = self.__get_tcp_motion_params(speed, mvacc, mvtime, **kwargs)
|
|
316
|
+
mvcoord = kwargs.get('mvcoord', int(is_tool_coord))
|
|
317
|
+
self._has_motion_cmd = True
|
|
318
|
+
motion_type = kwargs.get('motion_type', False)
|
|
319
|
+
radius = radius if radius is not None else -1
|
|
320
|
+
feedback_key, studio_wait = self._gen_feedback_key(wait, **kwargs)
|
|
321
|
+
if self.version_is_ge(1, 11, 100) or kwargs.get('debug', False):
|
|
322
|
+
if not is_tool_coord and relative:
|
|
323
|
+
ret = self.arm_cmd.move_relative(tcp_pos, spd, acc, mvt, radius, False, True, only_check_type, motion_type=motion_type, feedback_key=feedback_key)
|
|
324
|
+
else:
|
|
325
|
+
ret = self.arm_cmd.move_line_common(tcp_pos, spd, acc, mvt, radius, coord=1 if is_tool_coord else 0, is_axis_angle=True, only_check_type=only_check_type, motion_type=motion_type, feedback_key=feedback_key)
|
|
326
|
+
else:
|
|
327
|
+
ret = self.arm_cmd.move_line_aa(tcp_pos, spd, acc, mvt, mvcoord, int(relative), only_check_type, motion_type=motion_type)
|
|
328
|
+
trans_id = self._get_feedback_transid(feedback_key, studio_wait)
|
|
329
|
+
ret[0] = self._check_code(ret[0], is_move_cmd=True)
|
|
330
|
+
self.log_api_info('API -> set_position_aa -> code={}, pos={}, velo={}, acc={}'.format(
|
|
331
|
+
ret[0], tcp_pos, spd, acc), code=ret[0])
|
|
332
|
+
self._is_set_move = True
|
|
333
|
+
self._only_check_result = 0
|
|
334
|
+
if only_check_type > 0 and ret[0] == 0:
|
|
335
|
+
self._only_check_result = ret[3]
|
|
336
|
+
return APIState.HAS_ERROR if ret[3] != 0 else ret[0]
|
|
337
|
+
if only_check_type <= 0 and wait and ret[0] == 0:
|
|
338
|
+
code = self.wait_move(timeout, trans_id=trans_id)
|
|
339
|
+
self.__update_tcp_motion_params(spd, acc, mvt)
|
|
340
|
+
self._sync()
|
|
341
|
+
return code
|
|
342
|
+
if only_check_type <= 0 and (ret[0] >= 0 or self.get_is_moving()):
|
|
343
|
+
self.__update_tcp_motion_params(spd, acc, mvt)
|
|
344
|
+
return ret[0]
|
|
345
|
+
|
|
346
|
+
@xarm_wait_until_not_pause
|
|
347
|
+
@xarm_is_ready(_type='set')
|
|
348
|
+
def set_servo_cartesian_aa(self, mvpose, speed=None, mvacc=None, is_radian=None, is_tool_coord=False, relative=False, **kwargs):
|
|
349
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
350
|
+
assert len(mvpose) >= 6
|
|
351
|
+
tcp_pos = [to_radian(mvpose[i], is_radian or i <= 2) for i in range(6)]
|
|
352
|
+
spd, acc, mvt = self.__get_tcp_motion_params(speed, mvacc, self._mvtime, **kwargs)
|
|
353
|
+
|
|
354
|
+
tool_coord = kwargs.get('tool_coord', int(is_tool_coord))
|
|
355
|
+
|
|
356
|
+
self._has_motion_cmd = True
|
|
357
|
+
ret = self.arm_cmd.move_servo_cart_aa(mvpose=tcp_pos, mvvelo=spd, mvacc=acc, tool_coord=tool_coord, relative=int(relative))
|
|
358
|
+
ret[0] = self._check_code(ret[0], is_move_cmd=True, mode=1)
|
|
359
|
+
self.log_api_info('API -> set_servo_cartesian_aa -> code={}, pose={}, velo={}, acc={}'.format(
|
|
360
|
+
ret[0], tcp_pos, spd, acc
|
|
361
|
+
), code=ret[0])
|
|
362
|
+
self._is_set_move = True
|
|
363
|
+
return ret[0]
|
|
364
|
+
|
|
365
|
+
def _set_servo_angle_absolute(self, angles, speed=None, mvacc=None, mvtime=None,
|
|
366
|
+
is_radian=None, wait=False, timeout=None, radius=None, **kwargs):
|
|
367
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
368
|
+
only_check_type = kwargs.get('only_check_type', self._only_check_type)
|
|
369
|
+
joints = self._last_angles.copy()
|
|
370
|
+
for i in range(min(len(self._last_angles), len(angles))):
|
|
371
|
+
if i >= self.axis or angles[i] is None:
|
|
372
|
+
continue
|
|
373
|
+
joints[i] = to_radian(angles[i], is_radian)
|
|
374
|
+
if self._is_out_of_joint_range(joints[i], i):
|
|
375
|
+
return APIState.OUT_OF_RANGE
|
|
376
|
+
if kwargs.get('check', False):
|
|
377
|
+
_, limit = self.is_joint_limit(joints, True)
|
|
378
|
+
if _ == 0 and limit is True:
|
|
379
|
+
return APIState.JOINT_LIMIT
|
|
380
|
+
joints[5] = 0 if self.axis <= 5 else joints[5]
|
|
381
|
+
joints[6] = 0 if self.axis <= 6 else joints[6]
|
|
382
|
+
spd, acc, mvt = self.__get_joint_motion_params(speed, mvacc, mvtime, is_radian=is_radian, **kwargs)
|
|
383
|
+
self._has_motion_cmd = True
|
|
384
|
+
feedback_key, studio_wait = self._gen_feedback_key(wait, **kwargs)
|
|
385
|
+
if self.version_is_ge(1, 5, 20) and radius is not None and radius >= 0:
|
|
386
|
+
ret = self.arm_cmd.move_jointb(joints, spd, acc, radius, only_check_type, feedback_key=feedback_key)
|
|
387
|
+
else:
|
|
388
|
+
ret = self.arm_cmd.move_joint(joints, spd, acc, mvt, only_check_type, feedback_key=feedback_key)
|
|
389
|
+
trans_id = self._get_feedback_transid(feedback_key, studio_wait, kwargs.get('is_pop', True))
|
|
390
|
+
ret[0] = self._check_code(ret[0], is_move_cmd=True)
|
|
391
|
+
self.log_api_info('API -> set_servo_angle -> code={}, angles={}, velo={}, acc={}, radius={}'.format(
|
|
392
|
+
ret[0], joints, spd, acc, radius
|
|
393
|
+
), code=ret[0])
|
|
394
|
+
self._is_set_move = True
|
|
395
|
+
self._only_check_result = 0
|
|
396
|
+
if only_check_type > 0 and ret[0] == 0:
|
|
397
|
+
self._only_check_result = ret[3]
|
|
398
|
+
return APIState.HAS_ERROR if ret[3] != 0 else ret[0]
|
|
399
|
+
if only_check_type <= 0 and wait and ret[0] == 0:
|
|
400
|
+
code = self.wait_move(timeout, trans_id=trans_id)
|
|
401
|
+
self.__update_joint_motion_params(spd, acc, mvt)
|
|
402
|
+
self._sync()
|
|
403
|
+
return code
|
|
404
|
+
if only_check_type <= 0 and (ret[0] >= 0 or self.get_is_moving()):
|
|
405
|
+
self.__update_joint_motion_params(spd, acc, mvt, joints)
|
|
406
|
+
return ret[0]
|
|
407
|
+
|
|
408
|
+
def _set_servo_angle_relative(self, angles, speed=None, mvacc=None, mvtime=None,
|
|
409
|
+
is_radian=None, wait=False, timeout=None, radius=None, **kwargs):
|
|
410
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
411
|
+
only_check_type = kwargs.get('only_check_type', self._only_check_type)
|
|
412
|
+
if self.version_is_ge(1, 8, 100):
|
|
413
|
+
# use relative api
|
|
414
|
+
joints = [0] * 7
|
|
415
|
+
for i in range(min(7, len(angles))):
|
|
416
|
+
if i >= self.axis or angles[i] is None:
|
|
417
|
+
continue
|
|
418
|
+
joints[i] = to_radian(angles[i], is_radian)
|
|
419
|
+
self._has_motion_cmd = True
|
|
420
|
+
spd, acc, mvt = self.__get_joint_motion_params(speed, mvacc, mvtime, is_radian=is_radian, **kwargs)
|
|
421
|
+
radius = radius if radius is not None else -1
|
|
422
|
+
feedback_key, studio_wait = self._gen_feedback_key(wait, **kwargs)
|
|
423
|
+
joints[5] = 0 if self.axis <= 5 else joints[5]
|
|
424
|
+
joints[6] = 0 if self.axis <= 6 else joints[6]
|
|
425
|
+
ret = self.arm_cmd.move_relative(joints, spd, acc, mvt, radius, True, False, only_check_type, feedback_key=feedback_key)
|
|
426
|
+
trans_id = self._get_feedback_transid(feedback_key, studio_wait)
|
|
427
|
+
ret[0] = self._check_code(ret[0], is_move_cmd=True)
|
|
428
|
+
self.log_api_info('API -> set_relative_servo_angle -> code={}, angles={}, velo={}, acc={}, radius={}'.format(
|
|
429
|
+
ret[0], joints, spd, acc, radius
|
|
430
|
+
), code=ret[0])
|
|
431
|
+
self._is_set_move = True
|
|
432
|
+
self._only_check_result = 0
|
|
433
|
+
if only_check_type > 0 and ret[0] == 0:
|
|
434
|
+
self._only_check_result = ret[3]
|
|
435
|
+
return APIState.HAS_ERROR if ret[3] != 0 else ret[0]
|
|
436
|
+
if only_check_type <= 0 and wait and ret[0] == 0:
|
|
437
|
+
code = self.wait_move(timeout, trans_id=trans_id)
|
|
438
|
+
self.__update_joint_motion_params(spd, acc, mvt)
|
|
439
|
+
self._sync()
|
|
440
|
+
return code
|
|
441
|
+
if only_check_type <= 0 and (ret[0] >= 0 or self.get_is_moving()):
|
|
442
|
+
self.__update_joint_motion_params(spd, acc, mvt)
|
|
443
|
+
return ret[0]
|
|
444
|
+
else:
|
|
445
|
+
# use absolute api
|
|
446
|
+
joints = self._last_angles.copy()
|
|
447
|
+
for i in range(min(len(self._last_angles), len(angles))):
|
|
448
|
+
if i >= self.axis or angles[i] is None:
|
|
449
|
+
continue
|
|
450
|
+
joints[i] = to_radian(angles[i], is_radian)
|
|
451
|
+
if self._is_out_of_joint_range(joints[i], i):
|
|
452
|
+
return APIState.OUT_OF_RANGE
|
|
453
|
+
return self._set_servo_angle_absolute(joints, speed=speed, mvacc=mvacc, mvtime=mvtime, is_radian=True,
|
|
454
|
+
wait=wait, timeout=timeout, radius=radius, **kwargs)
|
|
455
|
+
|
|
456
|
+
@xarm_wait_until_not_pause
|
|
457
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
458
|
+
@xarm_is_ready(_type='set')
|
|
459
|
+
def set_servo_angle(self, servo_id=None, angle=None, speed=None, mvacc=None, mvtime=None,
|
|
460
|
+
relative=False, is_radian=None, wait=False, timeout=None, radius=None, **kwargs):
|
|
461
|
+
assert ((servo_id is None or servo_id == 8) and isinstance(angle, Iterable)) \
|
|
462
|
+
or (1 <= servo_id <= 7 and angle is not None and not isinstance(angle, Iterable)), \
|
|
463
|
+
'param servo_id or angle error'
|
|
464
|
+
if servo_id is not None and servo_id != 8:
|
|
465
|
+
if servo_id > self.axis or servo_id <= 0:
|
|
466
|
+
return APIState.SERVO_NOT_EXIST
|
|
467
|
+
angles = [math.inf if self.version_is_ge(2, 4, 101) else None] * 7
|
|
468
|
+
angles[servo_id - 1] = angle
|
|
469
|
+
else:
|
|
470
|
+
angles = angle
|
|
471
|
+
only_check_type = kwargs.get('only_check_type', self._only_check_type)
|
|
472
|
+
if only_check_type > 0 and wait:
|
|
473
|
+
code = self.wait_move(timeout=timeout)
|
|
474
|
+
if code != 0:
|
|
475
|
+
return code
|
|
476
|
+
code = self.__wait_sync()
|
|
477
|
+
if code != 0:
|
|
478
|
+
return code
|
|
479
|
+
if relative:
|
|
480
|
+
return self._set_servo_angle_relative(angles, speed=speed, mvacc=mvacc, mvtime=mvtime, is_radian=is_radian,
|
|
481
|
+
wait=wait, timeout=timeout, radius=radius, **kwargs)
|
|
482
|
+
else:
|
|
483
|
+
return self._set_servo_angle_absolute(angles, speed=speed, mvacc=mvacc, mvtime=mvtime, is_radian=is_radian,
|
|
484
|
+
wait=wait, timeout=timeout, radius=radius, **kwargs)
|
|
485
|
+
|
|
486
|
+
@xarm_is_ready(_type='set')
|
|
487
|
+
def set_servo_angle_j(self, angles, speed=None, mvacc=None, mvtime=None, is_radian=None, **kwargs):
|
|
488
|
+
# if not self._check_mode_is_correct(1):
|
|
489
|
+
# return APIState.MODE_IS_NOT_CORRECT
|
|
490
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
491
|
+
angs = [to_radian(angle, is_radian) for angle in angles]
|
|
492
|
+
for i in range(self.axis):
|
|
493
|
+
if self._is_out_of_joint_range(angs[i], i):
|
|
494
|
+
return APIState.OUT_OF_RANGE
|
|
495
|
+
while len(angs) < 7:
|
|
496
|
+
angs.append(0)
|
|
497
|
+
angs[5] = 0 if self.axis <= 5 else angs[5]
|
|
498
|
+
angs[6] = 0 if self.axis <= 6 else angs[6]
|
|
499
|
+
spd, acc, mvt = self.__get_joint_motion_params(speed, mvacc, mvtime, is_radian=is_radian, **kwargs)
|
|
500
|
+
self._has_motion_cmd = True
|
|
501
|
+
ret = self.arm_cmd.move_servoj(angs, spd, acc, mvt)
|
|
502
|
+
ret[0] = self._check_code(ret[0], is_move_cmd=True, mode=1)
|
|
503
|
+
self.log_api_info('API -> set_servo_angle_j -> code={}, angles={}, velo={}, acc={}'.format(
|
|
504
|
+
ret[0], angs, spd, acc
|
|
505
|
+
), code=ret[0])
|
|
506
|
+
self._is_set_move = True
|
|
507
|
+
return ret[0]
|
|
508
|
+
|
|
509
|
+
@xarm_is_ready(_type='set')
|
|
510
|
+
def set_servo_cartesian(self, mvpose, speed=None, mvacc=None, mvtime=None, is_radian=None, is_tool_coord=False, **kwargs):
|
|
511
|
+
# if not self._check_mode_is_correct(1):
|
|
512
|
+
# return APIState.MODE_IS_NOT_CORRECT
|
|
513
|
+
assert len(mvpose) >= 6
|
|
514
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
515
|
+
tcp_pos = [to_radian(mvpose[i], is_radian or i <= 2) for i in range(6)]
|
|
516
|
+
spd, acc, mvt = self.__get_tcp_motion_params(speed, mvacc, mvtime, **kwargs)
|
|
517
|
+
self._has_motion_cmd = True
|
|
518
|
+
ret = self.arm_cmd.move_servo_cartesian(tcp_pos, spd, acc, int(is_tool_coord))
|
|
519
|
+
ret[0] = self._check_code(ret[0], is_move_cmd=True, mode=1)
|
|
520
|
+
self.log_api_info('API -> set_servo_cartisian -> code={}, pose={}, velo={}, acc={}, is_tool_coord={}'.format(
|
|
521
|
+
ret[0], tcp_pos, spd, acc, is_tool_coord
|
|
522
|
+
), code=ret[0])
|
|
523
|
+
self._is_set_move = True
|
|
524
|
+
return ret[0]
|
|
525
|
+
|
|
526
|
+
@xarm_wait_until_not_pause
|
|
527
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
528
|
+
@xarm_is_ready(_type='set')
|
|
529
|
+
def move_circle(self, pose1, pose2, percent, speed=None, mvacc=None, mvtime=None, is_radian=None,
|
|
530
|
+
wait=False, timeout=None, is_tool_coord=False, is_axis_angle=False, **kwargs):
|
|
531
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
532
|
+
only_check_type = kwargs.get('only_check_type', self._only_check_type)
|
|
533
|
+
if only_check_type > 0 and wait:
|
|
534
|
+
code = self.wait_move(timeout=timeout)
|
|
535
|
+
if code != 0:
|
|
536
|
+
return code
|
|
537
|
+
pose_1 = []
|
|
538
|
+
pose_2 = []
|
|
539
|
+
for i in range(6):
|
|
540
|
+
pose_1.append(to_radian(pose1[i], is_radian or i <= 2))
|
|
541
|
+
pose_2.append(to_radian(pose2[i], is_radian or i <= 2))
|
|
542
|
+
spd, acc, mvt = self.__get_tcp_motion_params(speed, mvacc, mvtime, **kwargs)
|
|
543
|
+
self._has_motion_cmd = True
|
|
544
|
+
feedback_key, studio_wait = self._gen_feedback_key(wait, **kwargs)
|
|
545
|
+
if self.version_is_ge(1, 11, 100) or kwargs.get('debug', False):
|
|
546
|
+
ret = self.arm_cmd.move_circle_common(pose_1, pose_2, spd, acc, mvt, percent, coord=1 if is_tool_coord else 0, is_axis_angle=is_axis_angle, only_check_type=only_check_type, feedback_key=feedback_key)
|
|
547
|
+
else:
|
|
548
|
+
ret = self.arm_cmd.move_circle(pose_1, pose_2, spd, acc, mvt, percent, only_check_type)
|
|
549
|
+
trans_id = self._get_feedback_transid(feedback_key, studio_wait, kwargs.get('is_pop', True))
|
|
550
|
+
ret[0] = self._check_code(ret[0], is_move_cmd=True)
|
|
551
|
+
self.log_api_info('API -> move_circle -> code={}, pos1={}, pos2={}, percent={}%, velo={}, acc={}'.format(
|
|
552
|
+
ret[0], pose_1, pose_2, percent, spd, acc), code=ret[0])
|
|
553
|
+
self._is_set_move = True
|
|
554
|
+
self._only_check_result = 0
|
|
555
|
+
if only_check_type > 0 and ret[0] == 0:
|
|
556
|
+
self._only_check_result = ret[3]
|
|
557
|
+
return APIState.HAS_ERROR if ret[3] != 0 else ret[0]
|
|
558
|
+
if only_check_type <= 0 and wait and ret[0] == 0:
|
|
559
|
+
code = self.wait_move(timeout, trans_id=trans_id)
|
|
560
|
+
self.__update_tcp_motion_params(spd, acc, mvt)
|
|
561
|
+
self._sync()
|
|
562
|
+
return code
|
|
563
|
+
if only_check_type <= 0 and (ret[0] >= 0 or self.get_is_moving()):
|
|
564
|
+
self.__update_tcp_motion_params(spd, acc, mvt)
|
|
565
|
+
return ret[0]
|
|
566
|
+
|
|
567
|
+
@xarm_wait_until_not_pause
|
|
568
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
569
|
+
@xarm_is_ready(_type='set')
|
|
570
|
+
def move_gohome(self, speed=None, mvacc=None, mvtime=None, is_radian=None, wait=False, timeout=None, **kwargs):
|
|
571
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
572
|
+
only_check_type = kwargs.get('only_check_type', self._only_check_type)
|
|
573
|
+
if only_check_type > 0 and wait:
|
|
574
|
+
code = self.wait_move(timeout=timeout)
|
|
575
|
+
if code != 0:
|
|
576
|
+
return code
|
|
577
|
+
spd, acc, mvt = self.__get_joint_motion_params(speed, mvacc, mvtime, is_radian=is_radian, **kwargs)
|
|
578
|
+
self._has_motion_cmd = True
|
|
579
|
+
feedback_key, studio_wait = self._gen_feedback_key(wait, **kwargs)
|
|
580
|
+
ret = self.arm_cmd.move_gohome(spd, acc, mvt, only_check_type, feedback_key=feedback_key)
|
|
581
|
+
trans_id = self._get_feedback_transid(feedback_key, studio_wait)
|
|
582
|
+
ret[0] = self._check_code(ret[0], is_move_cmd=True)
|
|
583
|
+
self.log_api_info('API -> move_gohome -> code={}, velo={}, acc={}'.format(
|
|
584
|
+
ret[0], spd, acc
|
|
585
|
+
), code=ret[0])
|
|
586
|
+
self._is_set_move = True
|
|
587
|
+
self._only_check_result = 0
|
|
588
|
+
if only_check_type > 0 and ret[0] == 0:
|
|
589
|
+
self._only_check_result = ret[3]
|
|
590
|
+
return APIState.HAS_ERROR if ret[3] != 0 else ret[0]
|
|
591
|
+
if only_check_type <= 0 and wait and ret[0] == 0:
|
|
592
|
+
code = self.wait_move(timeout, trans_id=trans_id)
|
|
593
|
+
self._sync()
|
|
594
|
+
return code
|
|
595
|
+
return ret[0]
|
|
596
|
+
|
|
597
|
+
@xarm_is_ready(_type='set')
|
|
598
|
+
def move_arc_lines(self, paths, is_radian=None, times=1, first_pause_time=0.1, repeat_pause_time=0,
|
|
599
|
+
automatic_calibration=True, speed=None, mvacc=None, mvtime=None, wait=False):
|
|
600
|
+
assert len(paths) > 0, 'parameter paths error'
|
|
601
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
602
|
+
spd, acc, mvt = self.__get_tcp_motion_params(speed, mvacc, mvtime)
|
|
603
|
+
logger.info('move_arc_lines--begin')
|
|
604
|
+
if automatic_calibration:
|
|
605
|
+
_ = self.set_position(*paths[0], is_radian=is_radian, speed=spd, mvacc=acc, mvtime=mvt, wait=True)
|
|
606
|
+
if _ < 0:
|
|
607
|
+
logger.error('quit, api failed, code={}'.format(_))
|
|
608
|
+
return
|
|
609
|
+
_, angles = self.get_servo_angle(is_radian=True)
|
|
610
|
+
if first_pause_time > 0:
|
|
611
|
+
self.set_pause_time(first_pause_time)
|
|
612
|
+
last_used_joint_speed = self._last_joint_speed
|
|
613
|
+
|
|
614
|
+
def _move():
|
|
615
|
+
if automatic_calibration:
|
|
616
|
+
ret = self.set_servo_angle(angle=angles, is_radian=True, speed=0.8726646259971648, wait=False)
|
|
617
|
+
if ret < 0:
|
|
618
|
+
return -1
|
|
619
|
+
self._last_joint_speed = last_used_joint_speed
|
|
620
|
+
for path in paths:
|
|
621
|
+
if len(path) > 6 and path[6] >= 0:
|
|
622
|
+
radius = path[6]
|
|
623
|
+
else:
|
|
624
|
+
radius = 0
|
|
625
|
+
if self.has_error or self.is_stop:
|
|
626
|
+
return -2
|
|
627
|
+
ret = self.set_position(*path[:6], radius=radius, is_radian=is_radian, wait=False, speed=spd, mvacc=acc, mvtime=mvt)
|
|
628
|
+
if ret < 0:
|
|
629
|
+
return -1
|
|
630
|
+
return 0
|
|
631
|
+
count = 1
|
|
632
|
+
api_failed = False
|
|
633
|
+
|
|
634
|
+
try:
|
|
635
|
+
if times == 0:
|
|
636
|
+
while not self.has_error and not self.is_stop:
|
|
637
|
+
_ = _move()
|
|
638
|
+
if _ == -1:
|
|
639
|
+
api_failed = True
|
|
640
|
+
break
|
|
641
|
+
elif _ == -2:
|
|
642
|
+
break
|
|
643
|
+
count += 1
|
|
644
|
+
if repeat_pause_time > 0:
|
|
645
|
+
self.set_pause_time(repeat_pause_time)
|
|
646
|
+
if api_failed:
|
|
647
|
+
logger.error('quit, api error')
|
|
648
|
+
elif self._error_code != 0:
|
|
649
|
+
logger.error('quit, controller error')
|
|
650
|
+
elif self.is_stop:
|
|
651
|
+
logger.error('quit, emergency_stop')
|
|
652
|
+
else:
|
|
653
|
+
for i in range(times):
|
|
654
|
+
if self.has_error or self.is_stop:
|
|
655
|
+
break
|
|
656
|
+
_ = _move()
|
|
657
|
+
if _ == -1:
|
|
658
|
+
api_failed = True
|
|
659
|
+
break
|
|
660
|
+
elif _ == -2:
|
|
661
|
+
break
|
|
662
|
+
count += 1
|
|
663
|
+
if repeat_pause_time > 0:
|
|
664
|
+
self.set_pause_time(repeat_pause_time)
|
|
665
|
+
if api_failed:
|
|
666
|
+
logger.error('quit, api error')
|
|
667
|
+
elif self._error_code != 0:
|
|
668
|
+
logger.error('quit, controller error')
|
|
669
|
+
elif self.is_stop:
|
|
670
|
+
logger.error('quit, emergency_stop')
|
|
671
|
+
except:
|
|
672
|
+
pass
|
|
673
|
+
logger.info('move_arc_lines--end')
|
|
674
|
+
if wait:
|
|
675
|
+
self.wait_move()
|
|
676
|
+
self._sync()
|
|
677
|
+
|
|
678
|
+
@xarm_is_connected(_type='set')
|
|
679
|
+
def set_servo_attach(self, servo_id=None):
|
|
680
|
+
# assert isinstance(servo_id, int) and 1 <= servo_id <= 8
|
|
681
|
+
# ret = self.arm_cmd.set_brake(servo_id, 0)
|
|
682
|
+
logger.info('set_servo_attach--begin')
|
|
683
|
+
ret = self.motion_enable(servo_id=servo_id, enable=True)
|
|
684
|
+
self.set_state(0)
|
|
685
|
+
self._sync()
|
|
686
|
+
logger.info('set_servo_attach--end')
|
|
687
|
+
return ret
|
|
688
|
+
|
|
689
|
+
@xarm_is_connected(_type='set')
|
|
690
|
+
def set_servo_detach(self, servo_id=None):
|
|
691
|
+
"""
|
|
692
|
+
:param servo_id: 1-7, 8
|
|
693
|
+
:return:
|
|
694
|
+
"""
|
|
695
|
+
assert isinstance(servo_id, int) and 1 <= servo_id <= 8, 'The value of parameter servo_id can only be 1-8.'
|
|
696
|
+
ret = self.arm_cmd.set_brake(servo_id, 1)
|
|
697
|
+
self.log_api_info('API -> set_servo_detach -> code={}'.format(ret[0]), code=ret[0])
|
|
698
|
+
self._sync()
|
|
699
|
+
return ret[0]
|
|
700
|
+
|
|
701
|
+
@xarm_is_connected(_type='set')
|
|
702
|
+
def system_control(self, value=1):
|
|
703
|
+
ret = self.arm_cmd.system_control(value)
|
|
704
|
+
self.log_api_info('API -> system_control({}) -> code={}'.format(value, ret[0]), code=ret[0])
|
|
705
|
+
return ret[0]
|
|
706
|
+
|
|
707
|
+
@xarm_is_connected(_type='set')
|
|
708
|
+
def set_reduced_mode(self, on_off):
|
|
709
|
+
ret = self.arm_cmd.set_reduced_mode(int(on_off))
|
|
710
|
+
self.log_api_info('API -> set_reduced_mode -> code={}'.format(ret[0]), code=ret[0])
|
|
711
|
+
return ret[0]
|
|
712
|
+
|
|
713
|
+
@xarm_is_connected(_type='set')
|
|
714
|
+
def set_reduced_max_tcp_speed(self, speed):
|
|
715
|
+
ret = self.arm_cmd.set_reduced_linespeed(speed)
|
|
716
|
+
self.log_api_info('API -> set_reduced_linespeed -> code={}, speed={}'.format(ret[0], speed), code=ret[0])
|
|
717
|
+
return ret[0]
|
|
718
|
+
|
|
719
|
+
@xarm_is_connected(_type='set')
|
|
720
|
+
def set_reduced_max_joint_speed(self, speed, is_radian=None):
|
|
721
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
722
|
+
speed = to_radian(speed, is_radian)
|
|
723
|
+
ret = self.arm_cmd.set_reduced_jointspeed(speed)
|
|
724
|
+
self.log_api_info('API -> set_reduced_linespeed -> code={}, speed={}'.format(ret[0], speed), code=ret[0])
|
|
725
|
+
return ret[0]
|
|
726
|
+
|
|
727
|
+
@xarm_is_connected(_type='get')
|
|
728
|
+
def get_reduced_mode(self):
|
|
729
|
+
ret = self.arm_cmd.get_reduced_mode()
|
|
730
|
+
ret[0] = self._check_code(ret[0])
|
|
731
|
+
return ret[0], ret[1]
|
|
732
|
+
|
|
733
|
+
@xarm_is_connected(_type='get')
|
|
734
|
+
def get_reduced_states(self, is_radian=None):
|
|
735
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
736
|
+
ret = self.arm_cmd.get_reduced_states(79 if self.version_is_ge(1, 2, 11) else 21)
|
|
737
|
+
ret[0] = self._check_code(ret[0])
|
|
738
|
+
if ret[0] == 0:
|
|
739
|
+
if not is_radian:
|
|
740
|
+
ret[4] = round(math.degrees(ret[4]), 1)
|
|
741
|
+
if self.version_is_ge(1, 2, 11):
|
|
742
|
+
# ret[5] = list(map(math.degrees, ret[5]))
|
|
743
|
+
ret[5] = list(map(lambda x: round(math.degrees(x), 2), ret[5]))
|
|
744
|
+
return ret[0], ret[1:]
|
|
745
|
+
|
|
746
|
+
@xarm_is_connected(_type='set')
|
|
747
|
+
def set_reduced_tcp_boundary(self, boundary):
|
|
748
|
+
assert len(boundary) >= 6
|
|
749
|
+
boundary = list(map(int, boundary))
|
|
750
|
+
limits = [0] * 6
|
|
751
|
+
limits[0:2] = boundary[0:2] if boundary[0] >= boundary[1] else boundary[0:2][::-1]
|
|
752
|
+
limits[2:4] = boundary[2:4] if boundary[2] >= boundary[3] else boundary[2:4][::-1]
|
|
753
|
+
limits[4:6] = boundary[4:6] if boundary[4] >= boundary[5] else boundary[4:6][::-1]
|
|
754
|
+
ret = self.arm_cmd.set_xyz_limits(limits)
|
|
755
|
+
self.log_api_info('API -> set_reduced_tcp_boundary -> code={}, boundary={}'.format(ret[0], limits), code=ret[0])
|
|
756
|
+
return ret[0]
|
|
757
|
+
|
|
758
|
+
@xarm_is_connected(_type='set')
|
|
759
|
+
def set_reduced_joint_range(self, joint_range, is_radian=None):
|
|
760
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
761
|
+
assert len(joint_range) >= self.axis * 2
|
|
762
|
+
joint_range = list(map(float, joint_range))
|
|
763
|
+
limits = [0] * 14
|
|
764
|
+
for i in range(7):
|
|
765
|
+
if i < self.axis:
|
|
766
|
+
limits[i*2:i*2+2] = joint_range[i*2:i*2+2] if joint_range[i*2] <= joint_range[i*2+1] else joint_range[i*2:i*2+2][::-1]
|
|
767
|
+
if not is_radian:
|
|
768
|
+
limits = list(map(math.radians, limits))
|
|
769
|
+
# limits = list(map(lambda x: round(math.radians(x), 3), limits))
|
|
770
|
+
|
|
771
|
+
for i in range(self.axis):
|
|
772
|
+
device_type = int('{}1305'.format(self.axis)) if self.sn and int(self.sn[2:6]) >= 1305 and int(self.sn[2:6]) < 8500 else self.device_type
|
|
773
|
+
joint_limit = XCONF.Robot.JOINT_LIMITS.get(self.axis).get(device_type, [])
|
|
774
|
+
if i < len(joint_limit):
|
|
775
|
+
angle_range = joint_limit[i]
|
|
776
|
+
# angle_range = list(map(lambda x: round(x, 3), joint_limit[i]))
|
|
777
|
+
if limits[i * 2] < angle_range[0]:
|
|
778
|
+
limits[i * 2] = angle_range[0]
|
|
779
|
+
if limits[i * 2 + 1] > angle_range[1]:
|
|
780
|
+
limits[i * 2 + 1] = angle_range[1]
|
|
781
|
+
if limits[i * 2] >= angle_range[1]:
|
|
782
|
+
return APIState.OUT_OF_RANGE
|
|
783
|
+
if limits[i * 2 + 1] <= angle_range[0]:
|
|
784
|
+
return APIState.OUT_OF_RANGE
|
|
785
|
+
ret = self.arm_cmd.set_reduced_jrange(limits)
|
|
786
|
+
self.log_api_info('API -> set_reduced_joint_range -> code={}, boundary={}'.format(ret[0], limits), code=ret[0])
|
|
787
|
+
return ret[0]
|
|
788
|
+
|
|
789
|
+
@xarm_is_connected(_type='set')
|
|
790
|
+
def set_fense_mode(self, on_off):
|
|
791
|
+
ret = self.arm_cmd.set_fense_on(int(on_off))
|
|
792
|
+
self.log_api_info('API -> set_fense_mode -> code={}, on={}'.format(ret[0], on_off), code=ret[0])
|
|
793
|
+
return ret
|
|
794
|
+
|
|
795
|
+
@xarm_is_connected(_type='set')
|
|
796
|
+
def set_collision_rebound(self, on_off):
|
|
797
|
+
ret = self.arm_cmd.set_collis_reb(int(on_off))
|
|
798
|
+
self.log_api_info('API -> set_collision_rebound -> code={}, on={}'.format(ret[0], on_off), code=ret[0])
|
|
799
|
+
return ret
|
|
800
|
+
|
|
801
|
+
@xarm_is_connected(_type='set')
|
|
802
|
+
def set_timer(self, secs_later, tid, fun_code, param1=0, param2=0):
|
|
803
|
+
ret = self.arm_cmd.set_timer(secs_later, tid, fun_code, param1, param2)
|
|
804
|
+
return ret[0]
|
|
805
|
+
|
|
806
|
+
@xarm_is_connected(_type='set')
|
|
807
|
+
def cancel_timer(self, tid):
|
|
808
|
+
ret = self.arm_cmd.cancel_timer(tid)
|
|
809
|
+
return ret[0]
|
|
810
|
+
|
|
811
|
+
@xarm_wait_until_not_pause
|
|
812
|
+
@xarm_is_connected(_type='set')
|
|
813
|
+
def set_world_offset(self, offset, is_radian=None, wait=True):
|
|
814
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
815
|
+
assert isinstance(offset, Iterable) and len(offset) >= 6
|
|
816
|
+
world_offset = [0] * 6
|
|
817
|
+
for i in range(min(len(offset), 6)):
|
|
818
|
+
world_offset[i] = to_radian(offset[i], is_radian or i <= 2)
|
|
819
|
+
if wait:
|
|
820
|
+
if self._support_feedback:
|
|
821
|
+
self.wait_all_task_finish()
|
|
822
|
+
else:
|
|
823
|
+
self.wait_move()
|
|
824
|
+
ret = self.arm_cmd.set_world_offset(world_offset)
|
|
825
|
+
self.log_api_info('API -> set_world_offset -> code={}, offset={}'.format(ret[0], world_offset), code=ret[0])
|
|
826
|
+
return ret[0]
|
|
827
|
+
|
|
828
|
+
def reset(self, speed=None, mvacc=None, mvtime=None, is_radian=None, wait=False, timeout=None):
|
|
829
|
+
logger.info('reset--begin')
|
|
830
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
831
|
+
if not self._enable_report or self._stream_type != 'socket':
|
|
832
|
+
self.get_err_warn_code()
|
|
833
|
+
self.get_state()
|
|
834
|
+
if self._warn_code != 0:
|
|
835
|
+
self.clean_warn()
|
|
836
|
+
if self._error_code != 0:
|
|
837
|
+
self.clean_error()
|
|
838
|
+
self.motion_enable(enable=True, servo_id=8)
|
|
839
|
+
self.set_state(0)
|
|
840
|
+
if not self._is_ready:
|
|
841
|
+
self.motion_enable(enable=True, servo_id=8)
|
|
842
|
+
self.set_state(state=0)
|
|
843
|
+
self.move_gohome(speed=speed, mvacc=mvacc, mvtime=mvtime, is_radian=is_radian, wait=wait, timeout=timeout)
|
|
844
|
+
logger.info('reset--end')
|
|
845
|
+
|
|
846
|
+
# # This interface is no longer supported
|
|
847
|
+
# @xarm_is_ready(_type='set')
|
|
848
|
+
# def set_joints_torque(self, joints_torque):
|
|
849
|
+
# ret = self.arm_cmd.set_servot(joints_torque)
|
|
850
|
+
# self.log_api_info('API -> set_joints_torque -> code={}, joints_torque={}'.format(ret[0], joints_torque), code=ret[0])
|
|
851
|
+
# return ret[0]
|
|
852
|
+
|
|
853
|
+
@xarm_is_connected(_type='get')
|
|
854
|
+
def get_joints_torque(self, servo_id=None):
|
|
855
|
+
ret = self.arm_cmd.get_joint_tau()
|
|
856
|
+
ret[0] = self._check_code(ret[0])
|
|
857
|
+
if ret[0] == 0 and len(ret) > 7:
|
|
858
|
+
self._joints_torque = [float('{:.6f}'.format(ret[i])) for i in range(1, 8)]
|
|
859
|
+
if servo_id is None or servo_id == 8 or len(self._joints_torque) < servo_id:
|
|
860
|
+
return ret[0], list(self._joints_torque)
|
|
861
|
+
else:
|
|
862
|
+
return ret[0], self._joints_torque[servo_id - 1]
|
|
863
|
+
|
|
864
|
+
@xarm_is_connected(_type='get')
|
|
865
|
+
def get_safe_level(self):
|
|
866
|
+
ret = self.arm_cmd.get_safe_level()
|
|
867
|
+
return ret[0], ret[1]
|
|
868
|
+
|
|
869
|
+
@xarm_is_connected(_type='set')
|
|
870
|
+
def set_safe_level(self, level=4):
|
|
871
|
+
ret = self.arm_cmd.set_safe_level(level)
|
|
872
|
+
self.log_api_info('API -> set_safe_level -> code={}, level={}'.format(ret[0], level), code=ret[0])
|
|
873
|
+
return ret[0]
|
|
874
|
+
|
|
875
|
+
@xarm_wait_until_not_pause
|
|
876
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
877
|
+
@xarm_is_ready(_type='set')
|
|
878
|
+
def set_pause_time(self, sltime, wait=False):
|
|
879
|
+
assert isinstance(sltime, (int, float))
|
|
880
|
+
ret = self.arm_cmd.sleep_instruction(sltime)
|
|
881
|
+
if wait:
|
|
882
|
+
time.sleep(sltime)
|
|
883
|
+
else:
|
|
884
|
+
if time.monotonic() >= self._sleep_finish_time:
|
|
885
|
+
self._sleep_finish_time = time.monotonic() + sltime
|
|
886
|
+
else:
|
|
887
|
+
self._sleep_finish_time += sltime
|
|
888
|
+
self.log_api_info('API -> set_pause_time -> code={}, sltime={}'.format(ret[0], sltime), code=ret[0])
|
|
889
|
+
return ret[0]
|
|
890
|
+
|
|
891
|
+
def set_sleep_time(self, sltime, wait=False):
|
|
892
|
+
return self.set_pause_time(sltime, wait)
|
|
893
|
+
|
|
894
|
+
@xarm_wait_until_not_pause
|
|
895
|
+
@xarm_is_connected(_type='set')
|
|
896
|
+
def set_tcp_offset(self, offset, is_radian=None, wait=True, **kwargs):
|
|
897
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
898
|
+
assert isinstance(offset, Iterable) and len(offset) >= 6
|
|
899
|
+
tcp_offset = [0] * 6
|
|
900
|
+
for i in range(min(len(offset), 6)):
|
|
901
|
+
tcp_offset[i] = to_radian(offset[i], is_radian or i <= 2)
|
|
902
|
+
if wait:
|
|
903
|
+
if self._support_feedback:
|
|
904
|
+
self.wait_all_task_finish()
|
|
905
|
+
else:
|
|
906
|
+
self.wait_move()
|
|
907
|
+
ret = self.arm_cmd.set_tcp_offset(tcp_offset)
|
|
908
|
+
self.log_api_info('API -> set_tcp_offset -> code={}, offset={}'.format(ret[0], tcp_offset), code=ret[0])
|
|
909
|
+
return ret[0]
|
|
910
|
+
|
|
911
|
+
@xarm_wait_until_not_pause
|
|
912
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
913
|
+
@xarm_is_ready(_type='set')
|
|
914
|
+
def set_tcp_jerk(self, jerk):
|
|
915
|
+
ret = self.arm_cmd.set_tcp_jerk(jerk)
|
|
916
|
+
self.log_api_info('API -> set_tcp_jerk -> code={}, jerk={}'.format(ret[0], jerk), code=ret[0])
|
|
917
|
+
return ret[0]
|
|
918
|
+
|
|
919
|
+
@xarm_wait_until_not_pause
|
|
920
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
921
|
+
@xarm_is_ready(_type='set')
|
|
922
|
+
def set_tcp_maxacc(self, acc):
|
|
923
|
+
ret = self.arm_cmd.set_tcp_maxacc(acc)
|
|
924
|
+
self.log_api_info('API -> set_tcp_maxacc -> code={}, maxacc={}'.format(ret[0], acc), code=ret[0])
|
|
925
|
+
return ret[0]
|
|
926
|
+
|
|
927
|
+
@xarm_wait_until_not_pause
|
|
928
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
929
|
+
@xarm_is_ready(_type='set')
|
|
930
|
+
def set_joint_jerk(self, jerk, is_radian=None):
|
|
931
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
932
|
+
jerk = to_radian(jerk, is_radian)
|
|
933
|
+
ret = self.arm_cmd.set_joint_jerk(jerk)
|
|
934
|
+
self.log_api_info('API -> set_joint_jerk -> code={}, jerk={}'.format(ret[0], jerk), code=ret[0])
|
|
935
|
+
return ret[0]
|
|
936
|
+
|
|
937
|
+
@xarm_wait_until_not_pause
|
|
938
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
939
|
+
@xarm_is_ready(_type='set')
|
|
940
|
+
def set_joint_maxacc(self, maxacc, is_radian=None):
|
|
941
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
942
|
+
maxacc = to_radian(maxacc, is_radian)
|
|
943
|
+
ret = self.arm_cmd.set_joint_maxacc(maxacc)
|
|
944
|
+
self.log_api_info('API -> set_joint_maxacc -> code={}, maxacc={}'.format(ret[0], maxacc), code=ret[0])
|
|
945
|
+
return ret[0]
|
|
946
|
+
|
|
947
|
+
@xarm_wait_until_not_pause
|
|
948
|
+
@xarm_is_connected(_type='set')
|
|
949
|
+
def set_collision_sensitivity(self, value, wait=True):
|
|
950
|
+
assert isinstance(value, int) and 0 <= value <= 5
|
|
951
|
+
if self._support_feedback:
|
|
952
|
+
self.wait_all_task_finish()
|
|
953
|
+
else:
|
|
954
|
+
self.wait_move()
|
|
955
|
+
ret = self.arm_cmd.set_collis_sens(value)
|
|
956
|
+
self.set_state(0)
|
|
957
|
+
self.log_api_info('API -> set_collision_sensitivity -> code={}, sensitivity={}'.format(ret[0], value), code=ret[0])
|
|
958
|
+
return ret[0]
|
|
959
|
+
|
|
960
|
+
@xarm_wait_until_not_pause
|
|
961
|
+
@xarm_is_connected(_type='set')
|
|
962
|
+
def set_teach_sensitivity(self, value, wait=True):
|
|
963
|
+
assert isinstance(value, int) and 1 <= value <= 5
|
|
964
|
+
if wait:
|
|
965
|
+
if self._support_feedback:
|
|
966
|
+
self.wait_all_task_finish()
|
|
967
|
+
else:
|
|
968
|
+
self.wait_move()
|
|
969
|
+
ret = self.arm_cmd.set_teach_sens(value)
|
|
970
|
+
self.log_api_info('API -> set_teach_sensitivity -> code={}, sensitivity={}'.format(ret[0], value), code=ret[0])
|
|
971
|
+
return ret[0]
|
|
972
|
+
|
|
973
|
+
@xarm_wait_until_not_pause
|
|
974
|
+
@xarm_is_connected(_type='set')
|
|
975
|
+
def set_gravity_direction(self, direction, wait=True):
|
|
976
|
+
if wait:
|
|
977
|
+
if self._support_feedback:
|
|
978
|
+
self.wait_all_task_finish()
|
|
979
|
+
else:
|
|
980
|
+
self.wait_move()
|
|
981
|
+
ret = self.arm_cmd.set_gravity_dir(direction[:3])
|
|
982
|
+
self.log_api_info('API -> set_gravity_direction -> code={}, direction={}'.format(ret[0], direction), code=ret[0])
|
|
983
|
+
return ret[0]
|
|
984
|
+
|
|
985
|
+
@xarm_wait_until_not_pause
|
|
986
|
+
@xarm_is_connected(_type='set')
|
|
987
|
+
def set_mount_direction(self, base_tilt_deg, rotation_deg, is_radian=None):
|
|
988
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
989
|
+
t1 = base_tilt_deg
|
|
990
|
+
t2 = rotation_deg
|
|
991
|
+
|
|
992
|
+
if not is_radian:
|
|
993
|
+
t1 = math.radians(t1)
|
|
994
|
+
t2 = math.radians(t2)
|
|
995
|
+
|
|
996
|
+
# original G vect mounted on flat surface
|
|
997
|
+
G_normal = [0, 0, -1]
|
|
998
|
+
|
|
999
|
+
# rotation matrix introduced by 2 mounting angles
|
|
1000
|
+
R2 = [math.cos(-t2), -math.sin(-t2), 0, math.sin(-t2), math.cos(-t2), 0, 0, 0, 1]
|
|
1001
|
+
R1 = [math.cos(-t1), 0, math.sin(-t1), 0, 1, 0, -math.sin(-t1), 0, math.cos(-t1)]
|
|
1002
|
+
|
|
1003
|
+
Rot = [0] * 9
|
|
1004
|
+
g_new = [0] * 3
|
|
1005
|
+
|
|
1006
|
+
# Mat(Rot) = Mat(R2)*Mat(R1)
|
|
1007
|
+
# vect(g_new) = Mat(Rot)*vect(G_normal)
|
|
1008
|
+
for i in range(3):
|
|
1009
|
+
for j in range(3):
|
|
1010
|
+
Rot[i * 3 + j] += (
|
|
1011
|
+
R2[i * 3 + 0] * R1[0 * 3 + j] + R2[i * 3 + 1] * R1[1 * 3 + j] + R2[i * 3 + 2] * R1[2 * 3 + j])
|
|
1012
|
+
|
|
1013
|
+
g_new[i] = Rot[i * 3 + 0] * G_normal[0] + Rot[i * 3 + 1] * G_normal[1] + Rot[i * 3 + 2] * G_normal[2]
|
|
1014
|
+
|
|
1015
|
+
ret = self.arm_cmd.set_gravity_dir(g_new)
|
|
1016
|
+
self.log_api_info('API -> set_mount_direction -> code={}, tilt={}, rotation={}, direction={}'.format(ret[0], base_tilt_deg, rotation_deg, g_new), code=ret[0])
|
|
1017
|
+
return ret[0]
|
|
1018
|
+
|
|
1019
|
+
@xarm_is_connected(_type='set')
|
|
1020
|
+
def clean_conf(self):
|
|
1021
|
+
ret = self.arm_cmd.clean_conf()
|
|
1022
|
+
self.log_api_info('API -> clean_conf -> code={}'.format(ret[0]), code=ret[0])
|
|
1023
|
+
return ret[0]
|
|
1024
|
+
|
|
1025
|
+
@xarm_is_connected(_type='set')
|
|
1026
|
+
def save_conf(self):
|
|
1027
|
+
ret = self.arm_cmd.save_conf()
|
|
1028
|
+
self.log_api_info('API -> save_conf -> code={}'.format(ret[0]), code=ret[0])
|
|
1029
|
+
return ret[0]
|
|
1030
|
+
|
|
1031
|
+
@xarm_is_connected(_type='get')
|
|
1032
|
+
def get_inverse_kinematics(self, pose, input_is_radian=None, return_is_radian=None):
|
|
1033
|
+
input_is_radian = self._default_is_radian if input_is_radian is None else input_is_radian
|
|
1034
|
+
return_is_radian = self._default_is_radian if return_is_radian is None else return_is_radian
|
|
1035
|
+
assert len(pose) >= 6
|
|
1036
|
+
tcp_pose = [to_radian(pose[i], input_is_radian or i <= 2) for i in range(6)]
|
|
1037
|
+
ret = self.arm_cmd.get_ik(tcp_pose)
|
|
1038
|
+
angles = []
|
|
1039
|
+
ret[0] = self._check_code(ret[0])
|
|
1040
|
+
if ret[0] == 0:
|
|
1041
|
+
# angles = [ret[i][0] for i in range(1, 8)]
|
|
1042
|
+
angles = [ret[i] for i in range(1, 8)]
|
|
1043
|
+
if not return_is_radian:
|
|
1044
|
+
angles = [math.degrees(angle) for angle in angles]
|
|
1045
|
+
return ret[0], angles
|
|
1046
|
+
|
|
1047
|
+
@xarm_is_connected(_type='get')
|
|
1048
|
+
def get_forward_kinematics(self, angles, input_is_radian=None, return_is_radian=None):
|
|
1049
|
+
input_is_radian = self._default_is_radian if input_is_radian is None else input_is_radian
|
|
1050
|
+
return_is_radian = self._default_is_radian if return_is_radian is None else return_is_radian
|
|
1051
|
+
# assert len(angles) >= 7
|
|
1052
|
+
joints = [0] * 7
|
|
1053
|
+
for i in range(min(len(angles), 7)):
|
|
1054
|
+
joints[i] = to_radian(angles[i], input_is_radian)
|
|
1055
|
+
|
|
1056
|
+
ret = self.arm_cmd.get_fk(joints)
|
|
1057
|
+
pose = []
|
|
1058
|
+
ret[0] = self._check_code(ret[0])
|
|
1059
|
+
if ret[0] == 0:
|
|
1060
|
+
# pose = [ret[i][0] for i in range(1, 7)]
|
|
1061
|
+
pose = [ret[i] for i in range(1, 7)]
|
|
1062
|
+
if not return_is_radian:
|
|
1063
|
+
pose = [pose[i] if i < 3 else math.degrees(pose[i]) for i in range(len(pose))]
|
|
1064
|
+
return ret[0], pose
|
|
1065
|
+
|
|
1066
|
+
@xarm_is_connected(_type='get')
|
|
1067
|
+
def is_tcp_limit(self, pose, is_radian=None):
|
|
1068
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
1069
|
+
assert len(pose) >= 6
|
|
1070
|
+
tcp_pose = [to_radian(pose[i], is_radian or i <= 2, self._last_position[i]) for i in range(6)]
|
|
1071
|
+
ret = self.arm_cmd.is_tcp_limit(tcp_pose)
|
|
1072
|
+
self.log_api_info('API -> is_tcp_limit -> code={}, limit={}'.format(ret[0], ret[1]), code=ret[0])
|
|
1073
|
+
ret[0] = self._check_code(ret[0])
|
|
1074
|
+
if ret[0] == 0:
|
|
1075
|
+
return ret[0], bool(ret[1])
|
|
1076
|
+
else:
|
|
1077
|
+
return ret[0], None
|
|
1078
|
+
|
|
1079
|
+
@xarm_is_connected(_type='get')
|
|
1080
|
+
def is_joint_limit(self, joint, is_radian=None):
|
|
1081
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
1082
|
+
# assert len(joint) >= 7
|
|
1083
|
+
joints = [0] * 7
|
|
1084
|
+
for i in range(min(len(joint), 7)):
|
|
1085
|
+
joints[i] = to_radian(joint[i], is_radian, self._last_angles[i])
|
|
1086
|
+
|
|
1087
|
+
ret = self.arm_cmd.is_joint_limit(joints)
|
|
1088
|
+
self.log_api_info('API -> is_joint_limit -> code={}, limit={}'.format(ret[0], ret[1]), code=ret[0])
|
|
1089
|
+
ret[0] = self._check_code(ret[0])
|
|
1090
|
+
if ret[0] == 0:
|
|
1091
|
+
return ret[0], bool(ret[1])
|
|
1092
|
+
else:
|
|
1093
|
+
return ret[0], None
|
|
1094
|
+
|
|
1095
|
+
def emergency_stop(self):
|
|
1096
|
+
logger.info('emergency_stop--begin')
|
|
1097
|
+
self.set_state(4)
|
|
1098
|
+
expired = time.monotonic() + 3
|
|
1099
|
+
while self.state not in [4] and time.monotonic() < expired:
|
|
1100
|
+
self.set_state(4)
|
|
1101
|
+
time.sleep(0.1)
|
|
1102
|
+
self._sleep_finish_time = 0
|
|
1103
|
+
self._sync()
|
|
1104
|
+
logger.info('emergency_stop--end')
|
|
1105
|
+
|
|
1106
|
+
def send_cmd_async(self, command, timeout=None):
|
|
1107
|
+
pass
|
|
1108
|
+
|
|
1109
|
+
def send_cmd_sync(self, command=None):
|
|
1110
|
+
if command is None:
|
|
1111
|
+
return 0
|
|
1112
|
+
command = command.upper()
|
|
1113
|
+
return self._handle_gcode(command)
|
|
1114
|
+
|
|
1115
|
+
def _handle_gcode(self, command):
|
|
1116
|
+
def __handle_gcode_g(num):
|
|
1117
|
+
if num == 1: # G1 move_line, ex: G1 X{} Y{} Z{} A{roll} B{pitch} C{yaw} F{speed} Q{acc} T{}
|
|
1118
|
+
mvvelo = gcode_p.get_mvvelo(command)
|
|
1119
|
+
mvacc = gcode_p.get_mvacc(command)
|
|
1120
|
+
mvtime = gcode_p.get_mvtime(command)
|
|
1121
|
+
mvpose = gcode_p.get_poses(command)
|
|
1122
|
+
ret = self.set_position(*mvpose, radius=-1, speed=mvvelo, mvacc=mvacc, mvtime=mvtime)
|
|
1123
|
+
elif num == 2: # G2 move_circle, ex: G2 X{} Y{} Z{} A{} B{} C{} I{} J{} K{} L{} M{} N{} F{speed} Q{acc} T{}
|
|
1124
|
+
mvvelo = gcode_p.get_mvvelo(command)
|
|
1125
|
+
mvacc = gcode_p.get_mvacc(command)
|
|
1126
|
+
mvtime = gcode_p.get_mvtime(command)
|
|
1127
|
+
pos1 = gcode_p.get_poses(command, default=0)
|
|
1128
|
+
pos2 = gcode_p.get_joints(command, default=0)[:6]
|
|
1129
|
+
percent = gcode_p.get_mvradius(command, default=0)
|
|
1130
|
+
ret = self.move_circle(pos1, pos2, percent=percent, speed=mvvelo, mvacc=mvacc, mvtime=mvtime)
|
|
1131
|
+
elif num == 4: # G4 set_pause_time, ex: G4 T{}
|
|
1132
|
+
sltime = gcode_p.get_mvtime(command, default=0)
|
|
1133
|
+
ret = self.set_pause_time(sltime)
|
|
1134
|
+
elif num == 7: # G7 move_joint, ex: G7 I{} J{} K{} L{} M{} N{} O{} F{} Q{} T{}
|
|
1135
|
+
mvvelo = gcode_p.get_mvvelo(command)
|
|
1136
|
+
mvacc = gcode_p.get_mvacc(command)
|
|
1137
|
+
mvtime = gcode_p.get_mvtime(command)
|
|
1138
|
+
mvjoint = gcode_p.get_joints(command)
|
|
1139
|
+
ret = self.set_servo_angle(angle=mvjoint, speed=mvvelo, mvacc=mvacc, mvtime=mvtime)
|
|
1140
|
+
elif num == 8: # G8 move_gohome, ex: G8 F{} Q{} T{}
|
|
1141
|
+
mvvelo = gcode_p.get_mvvelo(command)
|
|
1142
|
+
mvacc = gcode_p.get_mvacc(command)
|
|
1143
|
+
mvtime = gcode_p.get_mvtime(command)
|
|
1144
|
+
ret = self.move_gohome(speed=mvvelo, mvacc=mvacc, mvtime=mvtime)
|
|
1145
|
+
elif num == 9: # G9 move_arc_line, ex: G9 X{} Y{} Z{} A{roll} B{pitch} C{yaw} R{radius} F{speed} Q{acc} T{}
|
|
1146
|
+
mvvelo = gcode_p.get_mvvelo(command)
|
|
1147
|
+
mvacc = gcode_p.get_mvacc(command)
|
|
1148
|
+
mvtime = gcode_p.get_mvtime(command)
|
|
1149
|
+
mvpose = gcode_p.get_poses(command)
|
|
1150
|
+
mvradii = gcode_p.get_mvradius(command, default=0)
|
|
1151
|
+
ret = self.set_position(*mvpose, speed=mvvelo, mvacc=mvacc, mvtime=mvtime, radius=mvradii)
|
|
1152
|
+
elif num == 11: # G11 set_servo_angle_j, ex: G11 I{} J{} K{} L{} M{} N{} O{} F{} Q{} T{}
|
|
1153
|
+
mvvelo = gcode_p.get_mvvelo(command)
|
|
1154
|
+
mvacc = gcode_p.get_mvacc(command)
|
|
1155
|
+
mvtime = gcode_p.get_mvtime(command)
|
|
1156
|
+
mvjoint = gcode_p.get_joints(command, default=0)
|
|
1157
|
+
ret = self.set_servo_angle_j(mvjoint, speed=mvvelo, mvacc=mvacc, mvtime=mvtime)
|
|
1158
|
+
elif num == 12: # G12 sleep, ex: G12 T{}
|
|
1159
|
+
mvtime = gcode_p.get_mvtime(command, default=0)
|
|
1160
|
+
time.sleep(mvtime)
|
|
1161
|
+
ret = 0
|
|
1162
|
+
else:
|
|
1163
|
+
logger.debug('command {} is not exist'.format(command))
|
|
1164
|
+
ret = APIState.CMD_NOT_EXIST, 'command {} is not exist'.format(command)
|
|
1165
|
+
return ret
|
|
1166
|
+
|
|
1167
|
+
def __handle_gcode_h(num):
|
|
1168
|
+
if num == 1: # H1 get_version, ex: H1
|
|
1169
|
+
ret = self.get_version()
|
|
1170
|
+
elif num == 10: # H10 system_control, ex: H10 V{}
|
|
1171
|
+
value = gcode_p.get_int_value(command, default=0)
|
|
1172
|
+
ret = self.system_control(value)
|
|
1173
|
+
elif num == 11: # H11 motion_enable, ex: H11 I{id} V{enable}
|
|
1174
|
+
value = gcode_p.get_int_value(command)
|
|
1175
|
+
servo_id = gcode_p.get_id_num(command, default=0)
|
|
1176
|
+
ret = self.motion_enable(enable=value, servo_id=servo_id)
|
|
1177
|
+
elif num == 12: # H12 set_state, ex: H12 V{state}
|
|
1178
|
+
value = gcode_p.get_int_value(command, default=0)
|
|
1179
|
+
ret = self.set_state(value)
|
|
1180
|
+
elif num == 13: # H13 get_state, ex: H13
|
|
1181
|
+
ret = self.get_state()
|
|
1182
|
+
elif num == 14: # H14 get_cmd_num, ex: H14
|
|
1183
|
+
ret = self.get_cmdnum()
|
|
1184
|
+
elif num == 15: # H15 get_error_warn_code, ex: H15
|
|
1185
|
+
ret = self.get_err_warn_code()
|
|
1186
|
+
elif num == 16: # H16 clean_error, ex: H16
|
|
1187
|
+
ret = self.clean_error()
|
|
1188
|
+
elif num == 17: # H17 clean_warn, ex: H17
|
|
1189
|
+
ret = self.clean_warn()
|
|
1190
|
+
elif num == 18: # H18 set_brake, ex: H18 I{id} V{open}
|
|
1191
|
+
value = gcode_p.get_int_value(command)
|
|
1192
|
+
servo_id = gcode_p.get_id_num(command, default=0)
|
|
1193
|
+
ret = self.arm_cmd.set_brake(servo_id, value)[0]
|
|
1194
|
+
elif num == 19: # H19 set_mode, ex: H19 V{mode}
|
|
1195
|
+
value = gcode_p.get_int_value(command, default=0)
|
|
1196
|
+
ret = self.set_mode(value)
|
|
1197
|
+
elif num == 31: # H31 set_tcp_jerk, ex: H31 V{jerk}
|
|
1198
|
+
value = gcode_p.get_float_value(command, default=-1)
|
|
1199
|
+
ret = self.set_tcp_jerk(value)
|
|
1200
|
+
elif num == 32: # H32 set_tcp_maxacc, ex: H32 V{maxacc}
|
|
1201
|
+
value = gcode_p.get_float_value(command, default=-1)
|
|
1202
|
+
ret = self.set_tcp_maxacc(value)
|
|
1203
|
+
elif num == 33: # H33 set_joint_jerk, ex: H33 V{jerk}
|
|
1204
|
+
value = gcode_p.get_float_value(command, default=-1)
|
|
1205
|
+
ret = self.set_joint_jerk(value)
|
|
1206
|
+
elif num == 34: # H34 set_joint_maxacc, ex: H34 V{maxacc}
|
|
1207
|
+
value = gcode_p.get_float_value(command, default=-1)
|
|
1208
|
+
ret = self.set_joint_maxacc(value)
|
|
1209
|
+
elif num == 35: # H35 set_tcp_offset, ex: H35 X{x} Y{y} Z{z} A{roll} B{pitch} C{yaw}
|
|
1210
|
+
pose = gcode_p.get_poses(command)
|
|
1211
|
+
ret = self.set_tcp_offset(pose)
|
|
1212
|
+
elif num == 36: # H36 set_tcp_load, ex: H36 I{weight} J{center_x} K{center_y} L{center_z}
|
|
1213
|
+
values = gcode_p.get_joints(command, default=0)
|
|
1214
|
+
ret = self.set_tcp_load(values[0], values[1:4])
|
|
1215
|
+
elif num == 37: # H37 set_collision_sensitivity, ex: H37 V{sensitivity}
|
|
1216
|
+
value = gcode_p.get_int_value(command, default=0)
|
|
1217
|
+
ret = self.set_collision_sensitivity(value)
|
|
1218
|
+
elif num == 38: # H38 set_teach_sensitivity, ex: H38 V{sensitivity}
|
|
1219
|
+
value = gcode_p.get_int_value(command, default=0)
|
|
1220
|
+
ret = self.set_teach_sensitivity(value)
|
|
1221
|
+
elif num == 39: # H39 clean_conf, ex: H39
|
|
1222
|
+
ret = self.clean_conf()
|
|
1223
|
+
elif num == 40: # H40 save_conf, ex: H40
|
|
1224
|
+
ret = self.save_conf()
|
|
1225
|
+
elif num == 41: # H41 get_position, ex: H41
|
|
1226
|
+
ret = self.get_position()
|
|
1227
|
+
elif num == 42: # H42 get_servo_angle, ex: H42
|
|
1228
|
+
ret = self.get_servo_angle()
|
|
1229
|
+
elif num == 43: # H43 get_ik, ex: H43 X{} Y{} Z{} A{roll} B{pitch} C{yaw}
|
|
1230
|
+
pose = gcode_p.get_poses(command, default=0)
|
|
1231
|
+
ret = self.get_inverse_kinematics(pose, input_is_radian=False, return_is_radian=False)
|
|
1232
|
+
elif num == 44: # H44 get_fk, ex: H44 I{} J{} K{} L{} M{} N{} O{}
|
|
1233
|
+
joint = gcode_p.get_joints(command, default=0)
|
|
1234
|
+
ret = self.get_forward_kinematics(joint, input_is_radian=False, return_is_radian=False)
|
|
1235
|
+
elif num == 45: # H45 is_joint_limit, ex: H45 I{} J{} K{} L{} M{} N{} O{}
|
|
1236
|
+
joint = gcode_p.get_joints(command)
|
|
1237
|
+
ret = self.is_joint_limit(joint, is_radian=False)
|
|
1238
|
+
elif num == 46: # H46 is_tcp_limit, ex: H46 X{} Y{} Z{} A{roll} B{pitch} C{yaw}
|
|
1239
|
+
pose = gcode_p.get_poses(command)
|
|
1240
|
+
ret = self.is_tcp_limit(pose, is_radian=False)
|
|
1241
|
+
elif num == 51: # H51 set_gravity_direction, ex: H51 X{} Y{} Z{} A{roll} B{pitch} C{yaw}
|
|
1242
|
+
pose = gcode_p.get_poses(command, default=0)
|
|
1243
|
+
ret = self.set_gravity_direction(pose)
|
|
1244
|
+
elif num == 101: # H101 set_servo_addr_16, ex: H101 I{id} D{addr} V{value}
|
|
1245
|
+
value = gcode_p.get_int_value(command)
|
|
1246
|
+
servo_id = gcode_p.get_id_num(command, default=0)
|
|
1247
|
+
addr = gcode_p.get_addr(command)
|
|
1248
|
+
ret = self.set_servo_addr_16(servo_id=servo_id, addr=addr, value=value)
|
|
1249
|
+
elif num == 102: # H102 get_servo_addr_16, ex: H102 I{id} D{addr}
|
|
1250
|
+
servo_id = gcode_p.get_id_num(command, default=0)
|
|
1251
|
+
addr = gcode_p.get_addr(command)
|
|
1252
|
+
ret = self.get_servo_addr_16(servo_id=servo_id, addr=addr)
|
|
1253
|
+
elif num == 103: # H103 set_servo_addr_32, ex: H103 I{id} D{addr} V{value}
|
|
1254
|
+
servo_id = gcode_p.get_id_num(command, default=0)
|
|
1255
|
+
addr = gcode_p.get_addr(command)
|
|
1256
|
+
value = gcode_p.get_int_value(command)
|
|
1257
|
+
ret = self.set_servo_addr_32(servo_id=servo_id, addr=addr, value=value)
|
|
1258
|
+
elif num == 104: # H104 get_servo_addr_32, ex: H104 I{id} D{addr}
|
|
1259
|
+
servo_id = gcode_p.get_id_num(command, default=0)
|
|
1260
|
+
addr = gcode_p.get_addr(command)
|
|
1261
|
+
ret = self.get_servo_addr_32(servo_id=servo_id, addr=addr)
|
|
1262
|
+
elif num == 105: # H105 set_servo_zero, ex: H105 I{id}
|
|
1263
|
+
servo_id = gcode_p.get_id_num(command, default=0)
|
|
1264
|
+
ret = self.set_servo_zero(servo_id=servo_id)
|
|
1265
|
+
elif num == 106: # H106 get_servo_debug_msg, ex: H106
|
|
1266
|
+
ret = self.get_servo_debug_msg()
|
|
1267
|
+
elif num == 114: # H114 servo_error_addr_r32, ex H114 I{id} D{addr}
|
|
1268
|
+
servo_id = gcode_p.get_id_num(command, default=0)
|
|
1269
|
+
addr = gcode_p.get_addr(command)
|
|
1270
|
+
ret = self.arm_cmd.servo_error_addr_r32(axis=servo_id, addr=addr)
|
|
1271
|
+
else:
|
|
1272
|
+
logger.debug('command {} is not exist'.format(command))
|
|
1273
|
+
ret = APIState.CMD_NOT_EXIST, 'command {} is not exist'.format(command)
|
|
1274
|
+
return ret
|
|
1275
|
+
|
|
1276
|
+
def __handle_gcode_m(num):
|
|
1277
|
+
if num == 116: # M116 set_gripper_enable, ex: M116 V{enable}
|
|
1278
|
+
value = gcode_p.get_int_value(command)
|
|
1279
|
+
ret = self.set_gripper_enable(value)
|
|
1280
|
+
elif num == 117: # M117 set_gripper_mode, ex: M117 V{mode}
|
|
1281
|
+
value = gcode_p.get_int_value(command)
|
|
1282
|
+
ret = self.set_gripper_mode(value)
|
|
1283
|
+
elif num == 118: # M118 set_gripper_zero, ex: M118
|
|
1284
|
+
ret = self.set_gripper_zero()
|
|
1285
|
+
elif num == 119: # M119 get_gripper_position, ex: M119
|
|
1286
|
+
ret = self.get_gripper_position()
|
|
1287
|
+
elif num == 120: # M120 set_gripper_position, ex: M120 V{pos}
|
|
1288
|
+
value = gcode_p.get_int_value(command)
|
|
1289
|
+
ret = self.set_gripper_position(value)
|
|
1290
|
+
elif num == 121: # M121 set_gripper_speed, ex: M121 V{speed}
|
|
1291
|
+
value = gcode_p.get_int_value(command)
|
|
1292
|
+
ret = self.set_gripper_speed(value)
|
|
1293
|
+
elif num == 125: # M125 get_gripper_err_code, ex: M125
|
|
1294
|
+
ret = self.get_gripper_err_code()
|
|
1295
|
+
elif num == 126: # M126 clean_gripper_error, ex: M126
|
|
1296
|
+
ret = self.clean_gripper_error()
|
|
1297
|
+
elif num == 127:
|
|
1298
|
+
ret = self.get_gripper_version()
|
|
1299
|
+
elif num == 131: # M131 get_tgpio_digital, ex: M131
|
|
1300
|
+
ret = self.get_tgpio_digital()
|
|
1301
|
+
elif num == 132: # M132 set_tgpio_digital, ex: M132 I{ionum} V{}
|
|
1302
|
+
ionum = gcode_p.get_id_num(command, default=0)
|
|
1303
|
+
value = gcode_p.get_int_value(command)
|
|
1304
|
+
ret = self.set_tgpio_digital(ionum, value)
|
|
1305
|
+
elif num == 133: # M133 get_tgpio_analog(0), ex: M133 I{ionum=0}
|
|
1306
|
+
ionum = gcode_p.get_id_num(command, default=0)
|
|
1307
|
+
ret = self.get_tgpio_analog(ionum=ionum)
|
|
1308
|
+
elif num == 134: # M134 get_tgpio_analog(1), ex: M134 I{ionum=1}
|
|
1309
|
+
ionum = gcode_p.get_id_num(command, default=0)
|
|
1310
|
+
ret = self.get_tgpio_analog(ionum=ionum)
|
|
1311
|
+
elif num == 135:
|
|
1312
|
+
return self.get_tgpio_version()
|
|
1313
|
+
else:
|
|
1314
|
+
logger.debug('command {} is not exist'.format(command))
|
|
1315
|
+
ret = APIState.CMD_NOT_EXIST, 'command {} is not exist'.format(command)
|
|
1316
|
+
return ret
|
|
1317
|
+
|
|
1318
|
+
def __handle_gcode_d(num):
|
|
1319
|
+
if num == 11: # D11 I{id}
|
|
1320
|
+
id_num = gcode_p.get_id_num(command, default=None)
|
|
1321
|
+
ret = self.get_servo_error_code(id_num)
|
|
1322
|
+
elif num == 12: # D12 I{id}
|
|
1323
|
+
id_num = gcode_p.get_id_num(command, default=None)
|
|
1324
|
+
if id_num == 0:
|
|
1325
|
+
id_num = 8
|
|
1326
|
+
self.clean_error()
|
|
1327
|
+
self.clean_warn()
|
|
1328
|
+
self.motion_enable(enable=False, servo_id=id_num)
|
|
1329
|
+
ret = self.set_servo_detach(id_num)
|
|
1330
|
+
elif num == 13: # D13 I{id}
|
|
1331
|
+
id_num = gcode_p.get_id_num(command, default=None)
|
|
1332
|
+
if id_num == 0:
|
|
1333
|
+
id_num = 8
|
|
1334
|
+
self.set_servo_zero(id_num)
|
|
1335
|
+
ret = self.motion_enable(enable=True, servo_id=id_num)
|
|
1336
|
+
elif num == 21: # D21 I{id}
|
|
1337
|
+
id_num = gcode_p.get_id_num(command, default=None)
|
|
1338
|
+
self.clean_servo_pvl_err(id_num)
|
|
1339
|
+
ret = self.get_servo_error_code(id_num)
|
|
1340
|
+
else:
|
|
1341
|
+
logger.debug('command {} is not exist'.format(command))
|
|
1342
|
+
ret = APIState.CMD_NOT_EXIST, 'command {} is not exist'.format(command)
|
|
1343
|
+
return ret
|
|
1344
|
+
|
|
1345
|
+
def __handle_gcode_s(num):
|
|
1346
|
+
if num == 44: # S44 I{id}
|
|
1347
|
+
id_num = gcode_p.get_id_num(command, default=None)
|
|
1348
|
+
ret = self.get_servo_all_pids(id_num)
|
|
1349
|
+
elif num == 45:
|
|
1350
|
+
id_num = gcode_p.get_id_num(command, default=1)
|
|
1351
|
+
ret = self.get_servo_version(servo_id=id_num)
|
|
1352
|
+
else:
|
|
1353
|
+
logger.debug('command {} is not exist'.format(command))
|
|
1354
|
+
ret = APIState.CMD_NOT_EXIST, 'command {} is not exist'.format(command)
|
|
1355
|
+
return ret
|
|
1356
|
+
|
|
1357
|
+
def __handle_gcode_c(num):
|
|
1358
|
+
if num == 131: # C131 get_cgpio_digital, ex: C131
|
|
1359
|
+
ret = self.get_cgpio_digital()
|
|
1360
|
+
elif num == 132: # C132 get_cgpio_analog(0), ex: C132 I{ionum=0}
|
|
1361
|
+
ionum = gcode_p.get_id_num(command, default=0)
|
|
1362
|
+
ret = self.get_cgpio_analog(ionum)
|
|
1363
|
+
elif num == 133: # C133 get_cgpio_analog(1), ex: C133 I{ionum=1}
|
|
1364
|
+
ionum = gcode_p.get_id_num(command, default=1)
|
|
1365
|
+
ret = self.get_cgpio_analog(ionum)
|
|
1366
|
+
elif num == 134: # C134 set_cgpio_digital, ex: C134 I{ionum} V{value}
|
|
1367
|
+
ionum = gcode_p.get_id_num(command, default=0)
|
|
1368
|
+
value = gcode_p.get_int_value(command)
|
|
1369
|
+
ret = self.set_cgpio_digital(ionum, value)
|
|
1370
|
+
elif num == 135: # C135 set_cgpio_analog(0, v), ex: C135 I{ionum=0} V{value}
|
|
1371
|
+
ionum = gcode_p.get_id_num(command, default=0)
|
|
1372
|
+
value = gcode_p.get_float_value(command)
|
|
1373
|
+
ret = self.set_cgpio_analog(ionum, value)
|
|
1374
|
+
elif num == 136: # C136 set_cgpio_analog(1, v), ex: C136 I{ionum=1} V{value}
|
|
1375
|
+
ionum = gcode_p.get_id_num(command, default=1)
|
|
1376
|
+
value = gcode_p.get_float_value(command)
|
|
1377
|
+
ret = self.set_cgpio_analog(ionum, value)
|
|
1378
|
+
elif num == 137: # C137 set_cgpio_digital_input_function, ex: C137 I{ionum} V{fun}
|
|
1379
|
+
ionum = gcode_p.get_id_num(command, default=0)
|
|
1380
|
+
value = gcode_p.get_int_value(command)
|
|
1381
|
+
ret = self.set_cgpio_digital_input_function(ionum, value)
|
|
1382
|
+
elif num == 138: # C138 set_cgpio_digital_output_function, ex: C138 I{ionum} V{fun}
|
|
1383
|
+
ionum = gcode_p.get_id_num(command, default=0)
|
|
1384
|
+
value = gcode_p.get_int_value(command)
|
|
1385
|
+
ret = self.set_cgpio_digital_output_function(ionum, value)
|
|
1386
|
+
elif num == 139: # C139 get_cgpio_state, ex: C139
|
|
1387
|
+
ret = self.get_cgpio_state()
|
|
1388
|
+
else:
|
|
1389
|
+
logger.debug('command {} is not exist'.format(command))
|
|
1390
|
+
ret = APIState.CMD_NOT_EXIST, 'command {} is not exist'.format(command)
|
|
1391
|
+
return ret
|
|
1392
|
+
|
|
1393
|
+
cmd_num = gcode_p.get_gcode_cmd_num(command, 'G')
|
|
1394
|
+
if cmd_num >= 0:
|
|
1395
|
+
return __handle_gcode_g(cmd_num)
|
|
1396
|
+
cmd_num = gcode_p.get_gcode_cmd_num(command, 'H')
|
|
1397
|
+
if cmd_num >= 0:
|
|
1398
|
+
return __handle_gcode_h(cmd_num)
|
|
1399
|
+
cmd_num = gcode_p.get_gcode_cmd_num(command, 'M')
|
|
1400
|
+
if cmd_num >= 0:
|
|
1401
|
+
return __handle_gcode_m(cmd_num)
|
|
1402
|
+
cmd_num = gcode_p.get_gcode_cmd_num(command, 'D')
|
|
1403
|
+
if cmd_num >= 0:
|
|
1404
|
+
return __handle_gcode_d(cmd_num)
|
|
1405
|
+
cmd_num = gcode_p.get_gcode_cmd_num(command, 'S')
|
|
1406
|
+
if cmd_num >= 0:
|
|
1407
|
+
return __handle_gcode_s(cmd_num)
|
|
1408
|
+
cmd_num = gcode_p.get_gcode_cmd_num(command, 'C')
|
|
1409
|
+
if cmd_num >= 0:
|
|
1410
|
+
return __handle_gcode_c(cmd_num)
|
|
1411
|
+
logger.debug('command {} is not exist'.format(command))
|
|
1412
|
+
return APIState.CMD_NOT_EXIST, 'command {} is not exist'.format(command)
|
|
1413
|
+
|
|
1414
|
+
@xarm_is_connected(_type='set')
|
|
1415
|
+
def run_gcode_file(self, path, **kwargs):
|
|
1416
|
+
times = kwargs.get('times', 1)
|
|
1417
|
+
init = kwargs.get('init', False)
|
|
1418
|
+
mode = kwargs.get('mode', 0)
|
|
1419
|
+
state = kwargs.get('state', 0)
|
|
1420
|
+
wait_seconds = kwargs.get('wait_seconds', 0)
|
|
1421
|
+
try:
|
|
1422
|
+
abs_path = os.path.abspath(path)
|
|
1423
|
+
if not os.path.exists(abs_path):
|
|
1424
|
+
raise FileNotFoundError
|
|
1425
|
+
with open(abs_path, 'r', encoding='utf-8') as f:
|
|
1426
|
+
lines = f.readlines()
|
|
1427
|
+
lines = [line.strip() for line in lines]
|
|
1428
|
+
if init:
|
|
1429
|
+
self.clean_error()
|
|
1430
|
+
self.clean_warn()
|
|
1431
|
+
self.motion_enable(True)
|
|
1432
|
+
self.set_mode(mode)
|
|
1433
|
+
self.set_state(state)
|
|
1434
|
+
if wait_seconds > 0:
|
|
1435
|
+
time.sleep(wait_seconds)
|
|
1436
|
+
|
|
1437
|
+
for i in range(times):
|
|
1438
|
+
for line in lines:
|
|
1439
|
+
line = line.strip()
|
|
1440
|
+
if not line:
|
|
1441
|
+
continue
|
|
1442
|
+
if not self.connected:
|
|
1443
|
+
logger.error('xArm is disconnect')
|
|
1444
|
+
return APIState.NOT_CONNECTED
|
|
1445
|
+
ret = self.send_cmd_sync(line)
|
|
1446
|
+
if isinstance(ret, int) and ret < 0:
|
|
1447
|
+
return ret
|
|
1448
|
+
return APIState.NORMAL
|
|
1449
|
+
except Exception as e:
|
|
1450
|
+
logger.error(e)
|
|
1451
|
+
return APIState.API_EXCEPTION
|
|
1452
|
+
|
|
1453
|
+
@xarm_is_connected(_type='set')
|
|
1454
|
+
def run_blockly_app(self, path, **kwargs):
|
|
1455
|
+
"""
|
|
1456
|
+
Run the app generated by xArmStudio software
|
|
1457
|
+
:param path: app path
|
|
1458
|
+
"""
|
|
1459
|
+
try:
|
|
1460
|
+
if not os.path.exists(path):
|
|
1461
|
+
dir_name = 'lite6' if self.axis == 6 and self.device_type == 9 else '850' if self.axis == 6 and self.device_type == 12 else 'xarm7T' if self.axis == 7 and self.device_type == 13 else 'xarm{}'.format(self.axis)
|
|
1462
|
+
path = os.path.join('/home/uf' if sys.platform.startswith('linux') else os.path.expanduser('~'), '.UFACTORY', 'projects', 'test', dir_name, 'app', 'myapp', path)
|
|
1463
|
+
if os.path.isdir(path):
|
|
1464
|
+
path = os.path.join(path, 'app.xml')
|
|
1465
|
+
if not os.path.exists(path):
|
|
1466
|
+
raise FileNotFoundError('{} is not found'.format(path))
|
|
1467
|
+
blockly_tool = BlocklyTool(path)
|
|
1468
|
+
succeed = blockly_tool.to_python(arm=self._api_instance, **kwargs)
|
|
1469
|
+
if succeed:
|
|
1470
|
+
times = kwargs.get('times', 1)
|
|
1471
|
+
highlight_callback = kwargs.get('highlight_callback', None)
|
|
1472
|
+
blockly_print = kwargs.get('blockly_print', print)
|
|
1473
|
+
blockly_exec = kwargs.get('blockly_exec', None)
|
|
1474
|
+
blockly_run_gcode = kwargs.get('blockly_run_gcode', None)
|
|
1475
|
+
connect_changed_callbacks = self._report_callbacks[self.REPORT_CONNECT_CHANGED_ID].copy()
|
|
1476
|
+
state_changed_callbacks = self._report_callbacks[self.REPORT_STATE_CHANGED_ID].copy()
|
|
1477
|
+
error_warn_changed_callbacks = self._report_callbacks[self.REPORT_ERROR_WARN_CHANGED_ID].copy()
|
|
1478
|
+
count_changed_callbacks = self._report_callbacks[self.REPORT_COUNT_CHANGED_ID].copy()
|
|
1479
|
+
code = APIState.NORMAL
|
|
1480
|
+
try:
|
|
1481
|
+
for _ in range(times):
|
|
1482
|
+
exec(blockly_tool.codes, {'arm': self._api_instance, 'highlight_callback': highlight_callback,
|
|
1483
|
+
'print': blockly_print, 'run_blockly': blockly_exec,
|
|
1484
|
+
'start_run_blockly': blockly_exec, 'start_run_gcode':blockly_run_gcode})
|
|
1485
|
+
except Exception as e:
|
|
1486
|
+
code = APIState.RUN_BLOCKLY_EXCEPTION
|
|
1487
|
+
blockly_print('run blockly app error: {}'.format(e))
|
|
1488
|
+
self._report_callbacks[self.REPORT_CONNECT_CHANGED_ID] = connect_changed_callbacks
|
|
1489
|
+
self._report_callbacks[self.REPORT_STATE_CHANGED_ID] = state_changed_callbacks
|
|
1490
|
+
self._report_callbacks[self.REPORT_ERROR_WARN_CHANGED_ID] = error_warn_changed_callbacks
|
|
1491
|
+
self._report_callbacks[self.REPORT_COUNT_CHANGED_ID] = count_changed_callbacks
|
|
1492
|
+
return code
|
|
1493
|
+
else:
|
|
1494
|
+
logger.error('The conversion is incomplete and some blocks are not yet supported.')
|
|
1495
|
+
return APIState.CONVERT_FAILED
|
|
1496
|
+
except Exception as e:
|
|
1497
|
+
logger.error(e)
|
|
1498
|
+
return APIState.API_EXCEPTION
|
|
1499
|
+
|
|
1500
|
+
@xarm_is_connected(_type='get')
|
|
1501
|
+
def get_hd_types(self):
|
|
1502
|
+
ret = self.arm_cmd.get_hd_types()
|
|
1503
|
+
return ret[0], ret[1:]
|
|
1504
|
+
|
|
1505
|
+
@xarm_is_connected(_type='set')
|
|
1506
|
+
def reload_dynamics(self):
|
|
1507
|
+
ret = self.arm_cmd.reload_dynamics()
|
|
1508
|
+
ret[0] = self._check_code(ret[0])
|
|
1509
|
+
self.log_api_info('API -> reload_dynamics -> code={}'.format(ret[0]), code=ret[0])
|
|
1510
|
+
return ret[0]
|
|
1511
|
+
|
|
1512
|
+
@xarm_wait_until_not_pause
|
|
1513
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
1514
|
+
@xarm_is_ready(_type='set')
|
|
1515
|
+
def set_counter_reset(self):
|
|
1516
|
+
ret = self.arm_cmd.cnter_reset()
|
|
1517
|
+
ret[0] = self._check_code(ret[0])
|
|
1518
|
+
self.log_api_info('API -> set_counter_reset -> code={}'.format(ret[0]), code=ret[0])
|
|
1519
|
+
return ret[0]
|
|
1520
|
+
|
|
1521
|
+
@xarm_wait_until_not_pause
|
|
1522
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
1523
|
+
@xarm_is_ready(_type='set')
|
|
1524
|
+
def set_counter_increase(self, val=1):
|
|
1525
|
+
ret = self.arm_cmd.cnter_plus()
|
|
1526
|
+
ret[0] = self._check_code(ret[0])
|
|
1527
|
+
self.log_api_info('API -> set_counter_increase -> code={}'.format(ret[0]), code=ret[0])
|
|
1528
|
+
return ret[0]
|
|
1529
|
+
|
|
1530
|
+
@xarm_is_connected(_type='set')
|
|
1531
|
+
def set_report_tau_or_i(self, tau_or_i=0):
|
|
1532
|
+
ret = self.arm_cmd.set_report_tau_or_i(int(tau_or_i))
|
|
1533
|
+
ret[0] = self._check_code(ret[0])
|
|
1534
|
+
self.log_api_info('API -> set_report_tau_or_i({}) -> code={}'.format(tau_or_i, ret[0]), code=ret[0])
|
|
1535
|
+
return ret[0]
|
|
1536
|
+
|
|
1537
|
+
@xarm_is_connected(_type='get')
|
|
1538
|
+
def get_report_tau_or_i(self):
|
|
1539
|
+
ret = self.arm_cmd.get_report_tau_or_i()
|
|
1540
|
+
return ret[0], ret[1]
|
|
1541
|
+
|
|
1542
|
+
@xarm_is_connected(_type='set')
|
|
1543
|
+
def set_self_collision_detection(self, on_off):
|
|
1544
|
+
ret = self.arm_cmd.set_self_collision_detection(int(on_off))
|
|
1545
|
+
ret[0] = self._check_code(ret[0])
|
|
1546
|
+
self.log_api_info('API -> set_self_collision_detection({}) -> code={}'.format(on_off, ret[0]), code=ret[0])
|
|
1547
|
+
return ret[0]
|
|
1548
|
+
|
|
1549
|
+
@xarm_is_connected(_type='set')
|
|
1550
|
+
def set_collision_tool_model(self, tool_type, *args, **kwargs):
|
|
1551
|
+
if tool_type == XCONF.CollisionToolType.BOX:
|
|
1552
|
+
assert ('z' in kwargs or len(args) >= 3) \
|
|
1553
|
+
and ('y' in kwargs or len(args) >= 2) \
|
|
1554
|
+
and ('x' in kwargs or len(args) >= 1), 'params error, must specify x,y,z parameter'
|
|
1555
|
+
x = kwargs.get('x') if 'x' in kwargs else args[0]
|
|
1556
|
+
y = kwargs.get('y') if 'y' in kwargs else args[1]
|
|
1557
|
+
z = kwargs.get('z') if 'z' in kwargs else args[2]
|
|
1558
|
+
x_offset = kwargs.get('x_offset') if 'x_offset' in kwargs else args[3] if len(args) >= 4 else 0
|
|
1559
|
+
y_offset = kwargs.get('y_offset') if 'y_offset' in kwargs else args[4] if len(args) >= 5 else 0
|
|
1560
|
+
z_offset = kwargs.get('z_offset') if 'z_offset' in kwargs else args[5] if len(args) >= 6 else 0
|
|
1561
|
+
params = [x, y, z, x_offset, y_offset, z_offset]
|
|
1562
|
+
elif tool_type == XCONF.CollisionToolType.CYLINDER:
|
|
1563
|
+
assert ('radius' in kwargs or len(args) >= 2) \
|
|
1564
|
+
and ('height' in kwargs or len(args) >= 1), 'params error, must specify radius,height parameter'
|
|
1565
|
+
radius = kwargs.get('radius') if 'radius' in kwargs else args[0]
|
|
1566
|
+
height = kwargs.get('height') if 'height' in kwargs else args[1]
|
|
1567
|
+
x_offset = kwargs.get('x_offset') if 'x_offset' in kwargs else args[2] if len(args) >= 3 else 0
|
|
1568
|
+
y_offset = kwargs.get('y_offset') if 'y_offset' in kwargs else args[3] if len(args) >= 4 else 0
|
|
1569
|
+
z_offset = kwargs.get('z_offset') if 'z_offset' in kwargs else args[4] if len(args) >= 5 else 0
|
|
1570
|
+
params = [radius, height, x_offset, y_offset, z_offset]
|
|
1571
|
+
else:
|
|
1572
|
+
params = [] if tool_type < XCONF.CollisionToolType.USE_PRIMITIVES else list(args)
|
|
1573
|
+
ret = self.arm_cmd.set_collision_tool_model(tool_type, params)
|
|
1574
|
+
ret[0] = self._check_code(ret[0])
|
|
1575
|
+
self.log_api_info('API -> set_collision_tool_model({}, {}) -> code={}'.format(tool_type, params, ret[0]), code=ret[0])
|
|
1576
|
+
return ret[0]
|
|
1577
|
+
|
|
1578
|
+
def get_firmware_config(self):
|
|
1579
|
+
cgpio_code, cgpio_states = self.get_cgpio_state()
|
|
1580
|
+
reduced_code, reduced_states = self.get_reduced_states()
|
|
1581
|
+
tau_code, tau_flag = self.get_report_tau_or_i()
|
|
1582
|
+
code = cgpio_code if reduced_code == 0 and tau_code == 0 else reduced_code if cgpio_code == 0 and tau_code == 0 else tau_code
|
|
1583
|
+
return code, {
|
|
1584
|
+
'COLL_SENS': self.collision_sensitivity, # 碰撞灵敏度
|
|
1585
|
+
'TEACH_SENS': self.teach_sensitivity, # 示教灵敏度
|
|
1586
|
+
'GRAV_DIR': self.gravity_direction, # 重力方向
|
|
1587
|
+
'TCP_LOAD': self.tcp_load, # TCP负载
|
|
1588
|
+
'TCP_OFFSET': self.position_offset, # TCP偏移
|
|
1589
|
+
'TCP_MAXACC': self.tcp_acc_limit[1], # TCP的最大加速度
|
|
1590
|
+
'TCP_JERK': self.tcp_jerk, # TCP加加速度
|
|
1591
|
+
'JOINT_MAXACC': self.joint_acc_limit[1], # 关节的最大加速度
|
|
1592
|
+
'JOINT_JERK': self.joint_jerk, # 关节加加速度
|
|
1593
|
+
'WORLD_OFFSET': self.world_offset, # 基坐标偏移
|
|
1594
|
+
'REPORT_TAU_OR_I': tau_flag, # 上报力矩还是电流
|
|
1595
|
+
'CGPIO_INPUT_FUNC_CONFIG': cgpio_states[10], # 控制器数字输入IO的配置功能
|
|
1596
|
+
'CGPIO_OUTPUT_FUNC_CONFIG': cgpio_states[11], # 控制器数字输出IO的配置功能
|
|
1597
|
+
'REDUCED_STATES': reduced_states, # 缩减模式的状态
|
|
1598
|
+
'GPIO_RESET_CONFIG': self.gpio_reset_config, # gpio自动复位配置
|
|
1599
|
+
'COLL_PARAMS': self.self_collision_params, # 碰撞模型参数
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
def set_firmware_config(self, config):
|
|
1603
|
+
code, old_config = self.get_firmware_config()
|
|
1604
|
+
if 'COLL_SENS' in config and config['COLL_SENS'] != old_config['COLL_SENS']:
|
|
1605
|
+
self.set_collision_sensitivity(config['COLL_SENS'])
|
|
1606
|
+
if 'TEACH_SENS' in config and config['TEACH_SENS'] != old_config['TEACH_SENS']:
|
|
1607
|
+
self.set_teach_sensitivity(config['TEACH_SENS'])
|
|
1608
|
+
if 'GRAV_DIR' in config and config['GRAV_DIR'] != old_config['GRAV_DIR']:
|
|
1609
|
+
self.set_gravity_direction(config['GRAV_DIR'])
|
|
1610
|
+
if 'TCP_LOAD' in config and config['TCP_LOAD'] != old_config['TCP_LOAD']:
|
|
1611
|
+
self.set_tcp_load(*config['TCP_LOAD'])
|
|
1612
|
+
if 'TCP_OFFSET' in config and config['TCP_OFFSET'] != old_config['TCP_OFFSET']:
|
|
1613
|
+
self.set_tcp_offset(config['TCP_OFFSET'])
|
|
1614
|
+
if 'TCP_MAXACC' in config and config['TCP_MAXACC'] != old_config['TCP_MAXACC']:
|
|
1615
|
+
self.set_tcp_maxacc(config['TCP_MAXACC'])
|
|
1616
|
+
if 'TCP_JERK' in config and config['TCP_JERK'] != old_config['TCP_JERK']:
|
|
1617
|
+
self.set_tcp_jerk(config['TCP_JERK'])
|
|
1618
|
+
if 'JOINT_MAXACC' in config and config['JOINT_MAXACC'] != old_config['JOINT_MAXACC']:
|
|
1619
|
+
self.set_joint_maxacc(config['JOINT_MAXACC'])
|
|
1620
|
+
if 'JOINT_JERK' in config and config['JOINT_JERK'] != old_config['JOINT_JERK']:
|
|
1621
|
+
self.set_joint_jerk(config['JOINT_JERK'])
|
|
1622
|
+
if 'WORLD_OFFSET' in config and config['WORLD_OFFSET'] != old_config['WORLD_OFFSET']:
|
|
1623
|
+
self.set_world_offset(config['WORLD_OFFSET'])
|
|
1624
|
+
if 'REPORT_TAU_OR_I' in config and config['REPORT_TAU_OR_I'] != old_config['REPORT_TAU_OR_I']:
|
|
1625
|
+
self.set_report_tau_or_i(config['REPORT_TAU_OR_I'])
|
|
1626
|
+
if 'GPIO_RESET_CONFIG' in config and config['GPIO_RESET_CONFIG'] != old_config['GPIO_RESET_CONFIG']:
|
|
1627
|
+
self.config_io_reset_when_stop(0, config['GPIO_RESET_CONFIG'][0])
|
|
1628
|
+
self.config_io_reset_when_stop(1, config['GPIO_RESET_CONFIG'][1])
|
|
1629
|
+
|
|
1630
|
+
if 'REDUCED_STATES' in config:
|
|
1631
|
+
states = config['REDUCED_STATES']
|
|
1632
|
+
old_states = old_config['REDUCED_STATES']
|
|
1633
|
+
if states[1] != old_states[1]:
|
|
1634
|
+
self.set_reduced_tcp_boundary(states[1])
|
|
1635
|
+
if states[2] != old_states[2]:
|
|
1636
|
+
self.set_reduced_max_tcp_speed(states[2])
|
|
1637
|
+
if states[3] != old_states[3]:
|
|
1638
|
+
self.set_reduced_max_joint_speed(states[3])
|
|
1639
|
+
if len(states) > 4 and len(old_states) > 4:
|
|
1640
|
+
if states[4] != old_states[4]:
|
|
1641
|
+
self.set_reduced_joint_range(states[4])
|
|
1642
|
+
if len(states) > 5 and len(old_states) > 5:
|
|
1643
|
+
if states[5] != old_states[5]:
|
|
1644
|
+
self.set_fense_mode(states[5])
|
|
1645
|
+
if len(states) > 6 and len(old_states) > 6:
|
|
1646
|
+
if states[4] != old_states[6]:
|
|
1647
|
+
self.set_collision_rebound(states[6])
|
|
1648
|
+
self.set_reduced_mode(states[0])
|
|
1649
|
+
|
|
1650
|
+
if 'CGPIO_INPUT_FUNC_CONFIG' in config and config['CGPIO_INPUT_FUNC_CONFIG'] != old_config['CGPIO_INPUT_FUNC_CONFIG']:
|
|
1651
|
+
for i in range(len(config['CGPIO_INPUT_FUNC_CONFIG'])):
|
|
1652
|
+
if config['CGPIO_INPUT_FUNC_CONFIG'][i] != old_config['CGPIO_INPUT_FUNC_CONFIG'][i]:
|
|
1653
|
+
self.set_cgpio_digital_input_function(i, config['CGPIO_INPUT_FUNC_CONFIG'][i])
|
|
1654
|
+
if 'CGPIO_OUTPUT_FUNC_CONFIG' in config and config['CGPIO_OUTPUT_FUNC_CONFIG'] != old_config['CGPIO_OUTPUT_FUNC_CONFIG']:
|
|
1655
|
+
for i in range(len(config['CGPIO_OUTPUT_FUNC_CONFIG'])):
|
|
1656
|
+
if config['CGPIO_OUTPUT_FUNC_CONFIG'][i] != old_config['CGPIO_OUTPUT_FUNC_CONFIG'][i]:
|
|
1657
|
+
self.set_cgpio_digital_output_function(i, config['CGPIO_OUTPUT_FUNC_CONFIG'][i])
|
|
1658
|
+
|
|
1659
|
+
if 'COLL_PARAMS' in config and config['COLL_PARAMS'] != old_config['COLL_PARAMS']:
|
|
1660
|
+
if config['COLL_PARAMS'][0] != old_config['COLL_PARAMS'][0]:
|
|
1661
|
+
self.set_self_collision_detection(config['COLL_PARAMS'][0])
|
|
1662
|
+
if config['COLL_PARAMS'][1] != old_config['COLL_PARAMS'][1] or config['COLL_PARAMS'][2] != old_config['COLL_PARAMS'][2]:
|
|
1663
|
+
self.set_collision_tool_model(config['COLL_PARAMS'][1], *config['COLL_PARAMS'][2])
|
|
1664
|
+
|
|
1665
|
+
self.save_conf()
|
|
1666
|
+
|
|
1667
|
+
@xarm_is_connected(_type='get')
|
|
1668
|
+
def get_power_board_version(self):
|
|
1669
|
+
ret = self.arm_cmd.get_power_board_version()
|
|
1670
|
+
ret[0] = self._check_code(ret[0])
|
|
1671
|
+
return ret[0], ret[1:]
|
|
1672
|
+
|
|
1673
|
+
@xarm_is_connected(_type='get')
|
|
1674
|
+
def get_movement(self):
|
|
1675
|
+
ret = self.arm_cmd.get_movement()
|
|
1676
|
+
ret[0] = self._check_code(ret[0])
|
|
1677
|
+
return ret[0], ret[1]
|
|
1678
|
+
|
|
1679
|
+
@xarm_is_connected(_type='set')
|
|
1680
|
+
def vc_set_joint_velocity(self, speeds, is_radian=None, is_sync=True, check_mode=True, duration=-1):
|
|
1681
|
+
# if check_mode and not self._check_mode_is_correct(4):
|
|
1682
|
+
# return APIState.MODE_IS_NOT_CORRECT
|
|
1683
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
1684
|
+
jnt_v = [0] * 7
|
|
1685
|
+
for i, spd in enumerate(speeds):
|
|
1686
|
+
if i >= 7:
|
|
1687
|
+
break
|
|
1688
|
+
jnt_v[i] = to_radian(spd, is_radian)
|
|
1689
|
+
|
|
1690
|
+
ret = self.arm_cmd.vc_set_jointv(jnt_v, 1 if is_sync else 0, duration if self.version_is_ge(1, 8, 0) else -1)
|
|
1691
|
+
ret[0] = self._check_code(ret[0], is_move_cmd=True, mode=4)
|
|
1692
|
+
self.log_api_info('API -> vc_set_joint_velocity -> code={}, speeds={}, is_sync={}'.format(
|
|
1693
|
+
ret[0], jnt_v, is_sync
|
|
1694
|
+
), code=ret[0])
|
|
1695
|
+
return ret[0]
|
|
1696
|
+
|
|
1697
|
+
@xarm_is_connected(_type='set')
|
|
1698
|
+
def vc_set_cartesian_velocity(self, speeds, is_radian=None, is_tool_coord=False, check_mode=True, duration=-1):
|
|
1699
|
+
# if check_mode and not self._check_mode_is_correct(5):
|
|
1700
|
+
# return APIState.MODE_IS_NOT_CORRECT
|
|
1701
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
1702
|
+
line_v = [0] * 6
|
|
1703
|
+
for i, spd in enumerate(speeds):
|
|
1704
|
+
if i >= 6:
|
|
1705
|
+
break
|
|
1706
|
+
line_v[i] = spd if i <= 2 else to_radian(spd, is_radian)
|
|
1707
|
+
ret = self.arm_cmd.vc_set_linev(line_v, 1 if is_tool_coord else 0, duration if self.version_is_ge(1, 8, 0) else -1)
|
|
1708
|
+
ret[0] = self._check_code(ret[0], is_move_cmd=True, mode=5)
|
|
1709
|
+
self.log_api_info('API -> vc_set_cartesian_velocity -> code={}, speeds={}, is_tool_coord={}'.format(
|
|
1710
|
+
ret[0], line_v, is_tool_coord
|
|
1711
|
+
), code=ret[0])
|
|
1712
|
+
return ret[0]
|
|
1713
|
+
|
|
1714
|
+
@xarm_is_connected(_type='get')
|
|
1715
|
+
def calibrate_tcp_coordinate_offset(self, four_points, is_radian=None):
|
|
1716
|
+
assert len(four_points) >= 4, 'The parameter four_points must contain 4 TCP points'
|
|
1717
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
1718
|
+
points = []
|
|
1719
|
+
for i in range(4):
|
|
1720
|
+
assert len(four_points[i]) >= 6, 'Each TCP point in the parameter four_points must contain x/y/z/roll/pitch/yaw'
|
|
1721
|
+
points.append([four_points[i][j] if j <= 2 else to_radian(four_points[i][j], is_radian) for j in range(6)])
|
|
1722
|
+
ret = self.arm_cmd.cali_tcp_pose(points)
|
|
1723
|
+
ret[0] = self._check_code(ret[0])
|
|
1724
|
+
return ret[0], ret[1:]
|
|
1725
|
+
|
|
1726
|
+
@xarm_is_connected(_type='get')
|
|
1727
|
+
def calibrate_tcp_orientation_offset(self, rpy_be, rpy_bt, input_is_radian=None, return_is_radian=None):
|
|
1728
|
+
input_is_radian = self._default_is_radian if input_is_radian is None else input_is_radian
|
|
1729
|
+
return_is_radian = self._default_is_radian if return_is_radian is None else return_is_radian
|
|
1730
|
+
rpy_be_ = [to_radian(rpy_be[i], input_is_radian) for i in range(3)]
|
|
1731
|
+
rpy_bt_ = [to_radian(rpy_bt[i], input_is_radian) for i in range(3)]
|
|
1732
|
+
ret = self.arm_cmd.cali_tcp_orient(rpy_be_, rpy_bt_)
|
|
1733
|
+
ret[0] = self._check_code(ret[0])
|
|
1734
|
+
return ret[0], [ret[i+1] if return_is_radian else math.degrees(ret[i+1]) for i in range(3)]
|
|
1735
|
+
|
|
1736
|
+
@xarm_is_connected(_type='get')
|
|
1737
|
+
def calibrate_user_orientation_offset(self, three_points, mode=0, trust_ind=0, input_is_radian=None, return_is_radian=None):
|
|
1738
|
+
assert len(three_points) >= 3, 'The parameter three_points must contain 3 TCP points'
|
|
1739
|
+
input_is_radian = self._default_is_radian if input_is_radian is None else input_is_radian
|
|
1740
|
+
return_is_radian = self._default_is_radian if return_is_radian is None else return_is_radian
|
|
1741
|
+
points = []
|
|
1742
|
+
for i in range(3):
|
|
1743
|
+
assert len(three_points[i]) >= 6, 'Each TCP point in the parameter three_points must contain x/y/z/roll/pitch/yaw'
|
|
1744
|
+
points.append([three_points[i][j] if j <= 2 else to_radian(three_points[i][j], input_is_radian) for j in range(6)])
|
|
1745
|
+
ret = self.arm_cmd.cali_user_orient(points, mode=mode, trust_ind=trust_ind)
|
|
1746
|
+
ret[0] = self._check_code(ret[0])
|
|
1747
|
+
return ret[0], [ret[i+1] if return_is_radian else math.degrees(ret[i+1]) for i in range(3)]
|
|
1748
|
+
|
|
1749
|
+
@xarm_is_connected(_type='get')
|
|
1750
|
+
def calibrate_user_coordinate_offset(self, rpy_ub, pos_b_uorg, is_radian=None):
|
|
1751
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
1752
|
+
rpy_ub_ = [rpy_ub[i] if is_radian else math.radians(rpy_ub[i]) for i in range(3)]
|
|
1753
|
+
ret = self.arm_cmd.cali_user_pos(rpy_ub_, pos_b_uorg)
|
|
1754
|
+
ret[0] = self._check_code(ret[0])
|
|
1755
|
+
return ret[0], ret[1:4]
|
|
1756
|
+
|
|
1757
|
+
@xarm_is_connected(_type='set')
|
|
1758
|
+
def get_tcp_rotation_radius(self, value=6):
|
|
1759
|
+
ret = self.arm_cmd.get_tcp_rotation_radius(value)
|
|
1760
|
+
self.log_api_info('API -> get_tcp_rotation_radius -> code={}'.format(ret[0]), code=ret[0])
|
|
1761
|
+
ret[0] = self._check_code(ret[0])
|
|
1762
|
+
return ret[0], ret[1][0]
|
|
1763
|
+
|
|
1764
|
+
@xarm_is_connected(_type='set')
|
|
1765
|
+
def get_max_joint_velocity(self, eveloc, joint_pos, is_radian=None, return_is_radian=True):
|
|
1766
|
+
"""
|
|
1767
|
+
Obtain maximum joint angular velocity
|
|
1768
|
+
:param eveloc: Maximum TCP speed
|
|
1769
|
+
:param joint_pos: joint angle list (unit: rad if is_radian is True else °), angle should be a list of values
|
|
1770
|
+
whose length is the number of joints like [axis-1, axis-2, axis-3, axis-4, axis-5, axis-6, axis-7]
|
|
1771
|
+
:param is_radian: the param angles value is in radians or not, default is self.default_is_radian
|
|
1772
|
+
:param return_is_radian: the returned value is in radians or not, default is True
|
|
1773
|
+
"""
|
|
1774
|
+
is_radian = self._default_is_radian if is_radian is None else is_radian
|
|
1775
|
+
joints = [0] * 7
|
|
1776
|
+
for i in range(min(len(joint_pos), 7)):
|
|
1777
|
+
joints[i] = to_radian(joint_pos[i], is_radian)
|
|
1778
|
+
ret = self.arm_cmd.get_max_joint_velocity(eveloc, joints)
|
|
1779
|
+
return ret if return_is_radian else math.radians(ret)
|
|
1780
|
+
|
|
1781
|
+
@xarm_is_connected(_type='get')
|
|
1782
|
+
def iden_tcp_load(self, estimated_mass=0):
|
|
1783
|
+
protocol_identifier = self.arm_cmd.get_protocol_identifier()
|
|
1784
|
+
self.arm_cmd.set_protocol_identifier(2)
|
|
1785
|
+
self._keep_heart = False
|
|
1786
|
+
if self.version_is_ge(1, 9, 100) and estimated_mass <= 0:
|
|
1787
|
+
estimated_mass = 0.5
|
|
1788
|
+
ret = self.arm_cmd.iden_tcp_load(estimated_mass)
|
|
1789
|
+
self.arm_cmd.set_protocol_identifier(protocol_identifier)
|
|
1790
|
+
self._keep_heart = True
|
|
1791
|
+
self.log_api_info('API -> iden_tcp_load -> code={}'.format(ret[0]), code=ret[0])
|
|
1792
|
+
return self._check_code(ret[0]), ret[1:5]
|
|
1793
|
+
|
|
1794
|
+
@xarm_is_connected(_type='set')
|
|
1795
|
+
def set_cartesian_velo_continuous(self, on_off):
|
|
1796
|
+
ret = self.arm_cmd.set_cartesian_velo_continuous(int(on_off))
|
|
1797
|
+
ret[0] = self._check_code(ret[0])
|
|
1798
|
+
self.log_api_info('API -> set_cartesian_velo_continuous({}) -> code={}'.format(on_off, ret[0]), code=ret[0])
|
|
1799
|
+
return ret[0]
|
|
1800
|
+
|
|
1801
|
+
@xarm_is_connected(_type='set')
|
|
1802
|
+
def set_allow_approx_motion(self, on_off):
|
|
1803
|
+
ret = self.arm_cmd.set_allow_approx_motion(int(on_off))
|
|
1804
|
+
ret[0] = self._check_code(ret[0])
|
|
1805
|
+
self.log_api_info('API -> set_allow_approx_motion({}) -> code={}'.format(on_off, ret[0]), code=ret[0])
|
|
1806
|
+
return ret[0]
|
|
1807
|
+
|
|
1808
|
+
@xarm_is_connected(_type='get')
|
|
1809
|
+
def get_allow_approx_motion(self):
|
|
1810
|
+
ret = self.arm_cmd.get_allow_approx_motion()
|
|
1811
|
+
ret[0] = self._check_code(ret[0])
|
|
1812
|
+
self.log_api_info('API -> get_allow_approx_motion() -> code={}'.format(ret[0]), code=ret[0])
|
|
1813
|
+
return ret[0], ret[-1]
|
|
1814
|
+
|
|
1815
|
+
@xarm_is_connected(_type='get')
|
|
1816
|
+
def iden_joint_friction(self, sn=None):
|
|
1817
|
+
if sn is None:
|
|
1818
|
+
code, sn = self.get_robot_sn()
|
|
1819
|
+
if code != 0:
|
|
1820
|
+
self.log_api_info('iden_joint_friction -> get_robot_sn failed, code={}'.format(code), code=code)
|
|
1821
|
+
return APIState.API_EXCEPTION, -1
|
|
1822
|
+
if len(sn) != 14:
|
|
1823
|
+
self.log_api_info('iden_joint_friction, sn is not correct, sn={}'.format(sn), code=APIState.API_EXCEPTION)
|
|
1824
|
+
return APIState.API_EXCEPTION, -1
|
|
1825
|
+
sn = sn.upper()
|
|
1826
|
+
axis_map = {5: 'F', 6: 'I', 7: 'S'}
|
|
1827
|
+
valid_850 = self.is_850 and sn[0] == 'F' and sn[1] == 'X'
|
|
1828
|
+
valid_lite = self.is_lite6 and sn[0] == 'L' and sn[1] == 'I'
|
|
1829
|
+
valid_xarm7t = not self.is_850 and not self.is_lite6 and sn[0] == 'C' and sn[1] == 'S'
|
|
1830
|
+
valid_xarm = not self.is_850 and not self.is_lite6 and sn[0] == 'X' and sn[1] == axis_map.get(self.axis, '')
|
|
1831
|
+
if not (valid_850 or valid_lite or valid_xarm or valid_xarm7t):
|
|
1832
|
+
self.log_api_info('iden_joint_friction, sn is not correct, axis={}, type={}, sn={}'.format(self.axis, self.device_type, sn), code=APIState.API_EXCEPTION)
|
|
1833
|
+
return APIState.API_EXCEPTION, -1
|
|
1834
|
+
|
|
1835
|
+
protocol_identifier = self.arm_cmd.get_protocol_identifier()
|
|
1836
|
+
self.arm_cmd.set_protocol_identifier(2)
|
|
1837
|
+
self._keep_heart = False
|
|
1838
|
+
ret = self.arm_cmd.iden_joint_friction(sn)
|
|
1839
|
+
self.arm_cmd.set_protocol_identifier(protocol_identifier)
|
|
1840
|
+
self._keep_heart = True
|
|
1841
|
+
self.log_api_info('API -> iden_joint_friction -> code={}'.format(ret[0]), code=ret[0])
|
|
1842
|
+
return self._check_code(ret[0]), 0 if int(ret[1]) == 0 else -1
|
|
1843
|
+
|
|
1844
|
+
@xarm_wait_until_not_pause
|
|
1845
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
1846
|
+
@xarm_is_ready(_type='set')
|
|
1847
|
+
def wait_all_task_finish(self, timeout=None, **kwargs):
|
|
1848
|
+
if not self._support_feedback:
|
|
1849
|
+
return APIState.CMD_NOT_EXIST
|
|
1850
|
+
wait = kwargs.pop('wait', True)
|
|
1851
|
+
feedback_key, studio_wait = self._gen_feedback_key(wait, **kwargs)
|
|
1852
|
+
ret = self.arm_cmd.check_feedback(feedback_key=feedback_key)
|
|
1853
|
+
trans_id = self._get_feedback_transid(feedback_key, studio_wait)
|
|
1854
|
+
ret[0] = self._check_code(ret[0])
|
|
1855
|
+
if wait and ret[0] == 0:
|
|
1856
|
+
ret[0] = self._wait_feedback(timeout, trans_id=trans_id, ignore_log=True)[0]
|
|
1857
|
+
if ret[0] == 0:
|
|
1858
|
+
time.sleep(0.5)
|
|
1859
|
+
return ret[0]
|
|
1860
|
+
|
|
1861
|
+
@xarm_wait_until_not_pause
|
|
1862
|
+
@xarm_wait_until_cmdnum_lt_max
|
|
1863
|
+
@xarm_is_ready(_type='set')
|
|
1864
|
+
def send_hex_cmd(self, datas, timeout=10):
|
|
1865
|
+
ret = self.arm_cmd.send_hex_cmd(datas, timeout)
|
|
1866
|
+
return self._check_code(ret[0]), ret[1:]
|
|
1867
|
+
# ret = self.arm_cmd.send_hex_request(datas)
|
|
1868
|
+
# if ret == -1:
|
|
1869
|
+
# return [XCONF.UxbusState.ERR_NOTTCP]
|
|
1870
|
+
# ret = self.arm_cmd.recv_hex_request(ret, timeout)
|
|
1871
|
+
# return ret
|
|
1872
|
+
|
|
1873
|
+
@xarm_is_connected(_type='get')
|
|
1874
|
+
def get_trans_id(self):
|
|
1875
|
+
return self.arm_cmd.get_trans_id()
|
|
1876
|
+
|
|
1877
|
+
@xarm_is_connected(_type='set')
|
|
1878
|
+
def run_gcode_app(self, path=None, **kwargs):
|
|
1879
|
+
sock = None
|
|
1880
|
+
try:
|
|
1881
|
+
if not os.path.exists(path):
|
|
1882
|
+
dir_name = 'lite6' if self.axis == 6 and self.device_type == 9 else '850' if self.axis == 6 and self.device_type == 12 else 'xarm7T' if self.axis == 7 and self.device_type == 13 else 'xarm{}'.format(
|
|
1883
|
+
self.axis)
|
|
1884
|
+
path = os.path.join('/home/uf' if sys.platform.startswith('linux') else os.path.expanduser('~'), '.UFACTORY', 'projects', 'test', dir_name, 'gcode', path)
|
|
1885
|
+
if not os.path.exists(path):
|
|
1886
|
+
raise FileNotFoundError('{} is not found'.format(path))
|
|
1887
|
+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
1888
|
+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
1889
|
+
sock.setblocking(True)
|
|
1890
|
+
sock.settimeout(10)
|
|
1891
|
+
sock.connect((self._port, 504))
|
|
1892
|
+
with open(path, 'r') as f:
|
|
1893
|
+
datas = f.read()
|
|
1894
|
+
lines = datas.split('\n')
|
|
1895
|
+
is_continue = False
|
|
1896
|
+
code = APIState.NORMAL
|
|
1897
|
+
for line in lines:
|
|
1898
|
+
line = line.strip()
|
|
1899
|
+
if line.startswith(';('):
|
|
1900
|
+
is_continue = True
|
|
1901
|
+
if not line or is_continue:
|
|
1902
|
+
if line.endswith(')'):
|
|
1903
|
+
is_continue = False
|
|
1904
|
+
continue
|
|
1905
|
+
if line.startswith(';'):
|
|
1906
|
+
continue
|
|
1907
|
+
GCODE_PATTERN = r'([A-Z])([-+]?[0-9.]+)'
|
|
1908
|
+
CLEAN_PATTERN = r'\s+|\(.*?\)|;.*'
|
|
1909
|
+
data = re.sub(CLEAN_PATTERN, '', line.strip().upper())
|
|
1910
|
+
if not data:
|
|
1911
|
+
return -14
|
|
1912
|
+
if data[0] == '%':
|
|
1913
|
+
return -15
|
|
1914
|
+
if not re.findall(GCODE_PATTERN, data):
|
|
1915
|
+
return -16
|
|
1916
|
+
|
|
1917
|
+
sock.send(line.strip().encode('utf-8', 'replace') + b'\n')
|
|
1918
|
+
err, status, code, buffer1, buffer2 = sock.recv(5)
|
|
1919
|
+
if err != 0 or code != 0:
|
|
1920
|
+
return err if err != 0 else code
|
|
1921
|
+
self.wait_move(set_cnt=5)
|
|
1922
|
+
return code
|
|
1923
|
+
except Exception as e:
|
|
1924
|
+
code = -13
|
|
1925
|
+
return code
|
|
1926
|
+
finally:
|
|
1927
|
+
if sock:
|
|
1928
|
+
sock.close()
|