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.
Files changed (63) hide show
  1. xarm/__init__.py +2 -0
  2. xarm/build_backend.py +17 -0
  3. xarm/core/__init__.py +2 -0
  4. xarm/core/comm/__init__.py +5 -0
  5. xarm/core/comm/base.py +303 -0
  6. xarm/core/comm/serial_port.py +44 -0
  7. xarm/core/comm/socket_port.py +150 -0
  8. xarm/core/comm/uxbus_cmd_protocol.py +100 -0
  9. xarm/core/config/__init__.py +0 -0
  10. xarm/core/config/x_code.py +1427 -0
  11. xarm/core/config/x_config.py +553 -0
  12. xarm/core/utils/__init__.py +3 -0
  13. xarm/core/utils/convert.py +124 -0
  14. xarm/core/utils/crc16.py +76 -0
  15. xarm/core/utils/debug_print.py +21 -0
  16. xarm/core/utils/log.py +98 -0
  17. xarm/core/version.py +1 -0
  18. xarm/core/wrapper/__init__.py +11 -0
  19. xarm/core/wrapper/uxbus_cmd.py +1457 -0
  20. xarm/core/wrapper/uxbus_cmd_ser.py +94 -0
  21. xarm/core/wrapper/uxbus_cmd_tcp.py +305 -0
  22. xarm/tools/__init__.py +0 -0
  23. xarm/tools/blockly/__init__.py +1 -0
  24. xarm/tools/blockly/_blockly_base.py +416 -0
  25. xarm/tools/blockly/_blockly_handler.py +1338 -0
  26. xarm/tools/blockly/_blockly_highlight.py +94 -0
  27. xarm/tools/blockly/_blockly_node.py +61 -0
  28. xarm/tools/blockly/_blockly_tool.py +480 -0
  29. xarm/tools/blockly_tool.py +1864 -0
  30. xarm/tools/gcode.py +90 -0
  31. xarm/tools/list_ports.py +39 -0
  32. xarm/tools/modbus_tcp.py +205 -0
  33. xarm/tools/threads.py +30 -0
  34. xarm/tools/utils.py +36 -0
  35. xarm/version.py +1 -0
  36. xarm/wrapper/__init__.py +1 -0
  37. xarm/wrapper/studio_api.py +34 -0
  38. xarm/wrapper/xarm_api.py +4416 -0
  39. xarm/x3/__init__.py +2 -0
  40. xarm/x3/base.py +2638 -0
  41. xarm/x3/base_board.py +198 -0
  42. xarm/x3/code.py +62 -0
  43. xarm/x3/decorator.py +104 -0
  44. xarm/x3/events.py +166 -0
  45. xarm/x3/ft_sensor.py +264 -0
  46. xarm/x3/gpio.py +457 -0
  47. xarm/x3/grammar_async.py +21 -0
  48. xarm/x3/grammar_coroutine.py +24 -0
  49. xarm/x3/gripper.py +830 -0
  50. xarm/x3/modbus_tcp.py +84 -0
  51. xarm/x3/parse.py +110 -0
  52. xarm/x3/record.py +216 -0
  53. xarm/x3/report.py +204 -0
  54. xarm/x3/robotiq.py +220 -0
  55. xarm/x3/servo.py +485 -0
  56. xarm/x3/studio.py +138 -0
  57. xarm/x3/track.py +424 -0
  58. xarm/x3/utils.py +43 -0
  59. xarm/x3/xarm.py +1928 -0
  60. xarm_python_sdk-1.15.2.dist-info/METADATA +103 -0
  61. xarm_python_sdk-1.15.2.dist-info/RECORD +63 -0
  62. xarm_python_sdk-1.15.2.dist-info/WHEEL +4 -0
  63. xarm_python_sdk-1.15.2.dist-info/licenses/LICENSE +27 -0
xarm/x3/modbus_tcp.py ADDED
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env python3
2
+ # Software License Agreement (BSD License)
3
+ #
4
+ # Copyright (c) 2023, UFACTORY, Inc.
5
+ # All rights reserved.
6
+ #
7
+ # Author: Vinman <vinman.wen@ufactory.cc> <vinman.cub@gmail.com>
8
+ from .base import Base
9
+ from .decorator import xarm_is_connected
10
+
11
+
12
+ class ModbusTcp(Base):
13
+ def __init__(self):
14
+ super(ModbusTcp, self).__init__()
15
+
16
+ @xarm_is_connected(_type='get')
17
+ def read_coil_bits(self, addr, quantity):
18
+ """
19
+ func_code: 0x01
20
+ """
21
+ return self.arm_cmd.read_coil_bits(addr, quantity)
22
+
23
+ @xarm_is_connected(_type='get')
24
+ def read_input_bits(self, addr, quantity):
25
+ """
26
+ func_code: 0x02
27
+ """
28
+ return self.arm_cmd.read_input_bits(addr, quantity)
29
+
30
+ @xarm_is_connected(_type='get')
31
+ def read_holding_registers(self, addr, quantity, is_signed=False):
32
+ """
33
+ func_code: 0x03
34
+ """
35
+ return self.arm_cmd.read_holding_registers(addr, quantity, is_signed)
36
+
37
+ @xarm_is_connected(_type='get')
38
+ def read_input_registers(self, addr, quantity, is_signed=False):
39
+ """
40
+ func_code: 0x04
41
+ """
42
+ return self.arm_cmd.read_input_registers(addr, quantity, is_signed)
43
+
44
+ @xarm_is_connected(_type='set')
45
+ def write_single_coil_bit(self, addr, bit_val):
46
+ """
47
+ func_code: 0x05
48
+ """
49
+ return self.arm_cmd.write_single_coil_bit(addr, bit_val)
50
+
51
+ @xarm_is_connected(_type='set')
52
+ def write_single_holding_register(self, addr, reg_val):
53
+ """
54
+ func_code: 0x06
55
+ """
56
+ return self.arm_cmd.write_single_holding_register(addr, reg_val)
57
+
58
+ @xarm_is_connected(_type='set')
59
+ def write_multiple_coil_bits(self, addr, bits):
60
+ """
61
+ func_code: 0x0F
62
+ """
63
+ return self.arm_cmd.write_multiple_coil_bits(addr, bits)
64
+
65
+ @xarm_is_connected(_type='set')
66
+ def write_multiple_holding_registers(self, addr, regs):
67
+ """
68
+ func_code: 0x10
69
+ """
70
+ return self.arm_cmd.write_multiple_holding_registers(addr, regs)
71
+
72
+ @xarm_is_connected(_type='set')
73
+ def mask_write_holding_register(self, addr, and_mask, or_mask):
74
+ """
75
+ func_code: 0x16
76
+ """
77
+ return self.arm_cmd.mask_write_holding_register(addr, and_mask, or_mask)
78
+
79
+ @xarm_is_connected(_type='get')
80
+ def write_and_read_holding_registers(self, r_addr, r_quantity, w_addr, w_regs, is_signed=False):
81
+ """
82
+ func_code: 0x17
83
+ """
84
+ return self.arm_cmd.write_and_read_holding_registers(r_addr, r_quantity, w_addr, w_regs, is_signed)
xarm/x3/parse.py ADDED
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env python3
2
+ # Software License Agreement (MIT License)
3
+ #
4
+ # Copyright (c) 2018, UFACTORY, Inc.
5
+ # All rights reserved.
6
+ #
7
+ # Author: Vinman <vinman.wen@ufactory.cc> <vinman.cub@gmail.com>
8
+
9
+ import re
10
+
11
+ GCODE_PARAM_X = 'X' # TCP-X
12
+ GCODE_PARAM_Y = 'Y' # TCP-Y
13
+ GCODE_PARAM_Z = 'Z' # TCP-Z
14
+ GCODE_PARAM_A = 'A' # TCP-Roll
15
+ GCODE_PARAM_B = 'B' # TCP-Pitch
16
+ GCODE_PARAM_C = 'C' # TCP-Yaw
17
+ GCODE_PARAM_R = 'R' # TCP-Radius
18
+ GCODE_PARAM_I = 'I' # Joint-1
19
+ GCODE_PARAM_J = 'J' # Joint-2
20
+ GCODE_PARAM_K = 'K' # Joint-3
21
+ GCODE_PARAM_L = 'L' # Joint-4
22
+ GCODE_PARAM_M = 'M' # Joint-5
23
+ GCODE_PARAM_N = 'N' # Joint-6
24
+ GCODE_PARAM_O = 'O' # Joint-7
25
+ GCODE_PARAM_F = 'F' # Move-Speed
26
+ GCODE_PARAM_Q = 'Q' # Move-Acc
27
+ GCODE_PARAM_T = 'T' # Move-Time
28
+ GCODE_PARAM_V = 'V' # Value
29
+ GCODE_PARAM_D = 'D' # Addr
30
+
31
+
32
+ class GcodeParser:
33
+ def __init__(self):
34
+ self._int_val = 0
35
+ self._float_val = 0.0
36
+
37
+ @staticmethod
38
+ def __get_value(string, ch, return_type, default=None):
39
+ pattern = r'{}(\-?\d+\.?\d*)'.format(ch)
40
+ data = re.findall(pattern, string)
41
+ if len(data) > 0:
42
+ return return_type(data[0])
43
+ return default
44
+
45
+ @staticmethod
46
+ def __get_hex_value(string, ch, default=None):
47
+ pattern = r'{}(-?\w{{3,4}})'.format(ch)
48
+ data = re.findall(pattern, string)
49
+ if len(data) > 0:
50
+ return int(data[0], base=16)
51
+ return default
52
+
53
+ def _get_int_value(self, string, ch, default=None):
54
+ return self.__get_value(string, ch, int, default=default)
55
+
56
+ def _get_float_value(self, string, ch, default=None):
57
+ return self.__get_value(string, ch, float, default=default)
58
+
59
+ def get_int_value(self, string, default=None):
60
+ if default is None:
61
+ default = self._int_val
62
+ self._int_val = self._get_int_value(string, GCODE_PARAM_V, default=default)
63
+ return self._int_val
64
+ else:
65
+ return self._get_int_value(string, GCODE_PARAM_V, default=default)
66
+
67
+ def get_float_value(self, string, default=0):
68
+ return self._get_float_value(string, GCODE_PARAM_V, default=default)
69
+
70
+ def get_addr(self, string, default=0):
71
+ return self.__get_hex_value(string, GCODE_PARAM_D, default=default)
72
+
73
+ def get_gcode_cmd_num(self, string, ch):
74
+ return self._get_int_value(string, ch, default=-1)
75
+
76
+ def get_mvvelo(self, string, default=None):
77
+ return self._get_float_value(string, GCODE_PARAM_F, default=default)
78
+
79
+ def get_mvacc(self, string, default=None):
80
+ return self._get_float_value(string, GCODE_PARAM_Q, default=default)
81
+
82
+ def get_mvtime(self, string, default=None):
83
+ return self._get_float_value(string, GCODE_PARAM_T, default=default)
84
+
85
+ def get_mvradius(self, string, default=None):
86
+ return self._get_float_value(string, GCODE_PARAM_R, default=default)
87
+
88
+ def get_id_num(self, string, default=None):
89
+ return self._get_int_value(string, GCODE_PARAM_I, default=default)
90
+
91
+ def get_poses(self, string, default=None):
92
+ pose = [None] * 6
93
+ pose[0] = self._get_float_value(string[2:], GCODE_PARAM_X, default=default)
94
+ pose[1] = self._get_float_value(string[2:], GCODE_PARAM_Y, default=default)
95
+ pose[2] = self._get_float_value(string[2:], GCODE_PARAM_Z, default=default)
96
+ pose[3] = self._get_float_value(string[2:], GCODE_PARAM_A, default=default)
97
+ pose[4] = self._get_float_value(string[2:], GCODE_PARAM_B, default=default)
98
+ pose[5] = self._get_float_value(string[2:], GCODE_PARAM_C, default=default)
99
+ return pose
100
+
101
+ def get_joints(self, string, default=None):
102
+ joints = [None] * 7
103
+ joints[0] = self._get_float_value(string[2:], GCODE_PARAM_I, default=default)
104
+ joints[1] = self._get_float_value(string[2:], GCODE_PARAM_J, default=default)
105
+ joints[2] = self._get_float_value(string[2:], GCODE_PARAM_K, default=default)
106
+ joints[3] = self._get_float_value(string[2:], GCODE_PARAM_L, default=default)
107
+ joints[4] = self._get_float_value(string[2:], GCODE_PARAM_M, default=default)
108
+ joints[5] = self._get_float_value(string[2:], GCODE_PARAM_N, default=default)
109
+ joints[6] = self._get_float_value(string[2:], GCODE_PARAM_O, default=default)
110
+ return joints
xarm/x3/record.py ADDED
@@ -0,0 +1,216 @@
1
+ #!/usr/bin/env python3
2
+ # Software License Agreement (BSD License)
3
+ #
4
+ # Copyright (c) 2019, UFACTORY, Inc.
5
+ # All rights reserved.
6
+ #
7
+ # Author: Vinman <vinman.wen@ufactory.cc> <vinman.cub@gmail.com>
8
+
9
+ import json
10
+ import time
11
+ import uuid
12
+ from urllib import request
13
+ from .code import APIState
14
+ from ..core.config.x_config import XCONF
15
+ from ..core.utils.log import logger
16
+ from .base import Base
17
+ from .decorator import xarm_is_connected
18
+
19
+
20
+ class Record(Base):
21
+ def __init__(self):
22
+ super(Record, self).__init__()
23
+
24
+ @xarm_is_connected(_type='get')
25
+ def get_trajectories(self, ip=None):
26
+ if ip is None:
27
+ url = 'http://{}:18333/cmd'.format(self._port)
28
+ else:
29
+ url = 'http://{}:18333/cmd'.format(ip)
30
+ try:
31
+ data = {'cmd': 'xarm_list_trajs'}
32
+ req = request.Request(url, headers={'Content-Type': 'application/json'}, data=json.dumps(data).encode('utf-8'))
33
+ res = request.urlopen(req)
34
+ if res.code == 200:
35
+ result = json.loads(res.read().decode('utf-8'))
36
+ return result['res'][0], [{'name': item['name'], 'duration': item['count'] / 100} for item in result['res'][1]]
37
+ else:
38
+ return APIState.API_EXCEPTION, []
39
+ except Exception as e:
40
+ return APIState.API_EXCEPTION, []
41
+
42
+ @xarm_is_connected(_type='set')
43
+ def start_record_trajectory(self):
44
+ ret = self.arm_cmd.set_record_traj(1)
45
+ self.log_api_info('API -> start_record_trajectory -> code={}'.format(ret[0]), code=ret[0])
46
+ return ret[0]
47
+
48
+ @xarm_is_connected(_type='set')
49
+ def stop_record_trajectory(self, filename=None, **kwargs):
50
+ ret = self.arm_cmd.set_record_traj(0)
51
+ if isinstance(filename, str) and filename.strip():
52
+ ret2 = self.save_record_trajectory(filename, wait=True, timeout=10, **kwargs)
53
+ if ret2 != 0:
54
+ return ret2
55
+ self.log_api_info('API -> stop_record_trajectory -> code={}'.format(ret[0]), code=ret[0])
56
+ return ret[0]
57
+
58
+ @xarm_is_connected(_type='set')
59
+ def save_record_trajectory(self, filename, wait=True, timeout=2, **kwargs):
60
+ assert isinstance(filename, str) and filename.strip()
61
+ filename = filename.strip()
62
+ if not filename.endswith('.traj'):
63
+ full_filename = '{}.traj'.format(filename)
64
+ else:
65
+ full_filename = filename
66
+ self.get_trajectory_rw_status()
67
+ feedback_key, studio_wait = self._gen_feedback_key(wait, **kwargs)
68
+ ret = self.arm_cmd.save_traj(full_filename, wait_time=0, feedback_key=feedback_key)
69
+ trans_id = self._get_feedback_transid(feedback_key, studio_wait)
70
+ self.log_api_info('API -> save_record_trajectory -> code={}'.format(ret[0]), code=ret[0])
71
+ ret[0] = self._check_code(ret[0])
72
+ if ret[0] == 0 and wait:
73
+ return self.__wait_save_traj(timeout, trans_id, filename)
74
+ if ret[0] != 0:
75
+ logger.error('Save {} failed, ret={}'.format(filename, ret))
76
+ return ret[0]
77
+
78
+ def __check_traj_status(self, status, filename='unknown'):
79
+ if status == XCONF.TrajState.LOAD_SUCCESS:
80
+ logger.info('Load {} success'.format(filename))
81
+ return 0
82
+ elif status == XCONF.TrajState.LOAD_FAIL:
83
+ logger.error('Load {} failed'.format(filename))
84
+ return APIState.TRAJ_RW_FAILED
85
+ elif status == XCONF.TrajState.SAVE_SUCCESS:
86
+ logger.info('Save {} success'.format(filename))
87
+ return 0
88
+ elif status == XCONF.TrajState.SAVE_FAIL:
89
+ logger.error('Save {} failed'.format(filename))
90
+ return APIState.TRAJ_RW_FAILED
91
+ return -1
92
+
93
+ def __wait_traj_op(self, timeout, trans_id, filename='unknown', op='Load'):
94
+ if self._support_feedback and trans_id > 0:
95
+ code, feedback_code = self._wait_feedback(timeout, trans_id)
96
+ _, status = self.get_trajectory_rw_status()
97
+ if code == 0:
98
+ success_status = XCONF.TrajState.LOAD_SUCCESS if op == 'Load' else XCONF.TrajState.SAVE_SUCCESS
99
+ failure_status = XCONF.TrajState.LOAD_FAIL if op == 'Load' else XCONF.TrajState.SAVE_FAIL
100
+ status = success_status if feedback_code == XCONF.FeedbackCode.SUCCESS else failure_status if feedback_code == XCONF.FeedbackCode.FAILURE else status
101
+ return self.__check_traj_status(status, filename)
102
+ else:
103
+ expired = (time.monotonic() + timeout) if timeout is not None else 0
104
+ idle_cnts = 0
105
+ while timeout is None or time.monotonic() < expired:
106
+ time.sleep(0.1)
107
+ code, status = self.get_trajectory_rw_status()
108
+ if self._check_code(code) == 0:
109
+ if status == XCONF.TrajState.IDLE:
110
+ idle_cnts += 1
111
+ if idle_cnts >= 5:
112
+ logger.info('{} {} failed, idle'.format(op, filename))
113
+ return APIState.TRAJ_RW_FAILED
114
+ else:
115
+ code = self.__check_traj_status(status, filename)
116
+ if code >= 0:
117
+ return code
118
+ logger.warning('{} {} timeout'.format(op, filename))
119
+ return APIState.TRAJ_RW_TOUT
120
+
121
+ def __wait_load_traj(self, timeout, trans_id, filename='unknown'):
122
+ return self.__wait_traj_op(timeout, trans_id, filename, 'Load')
123
+
124
+ def __wait_save_traj(self, timeout, trans_id, filename='unknown'):
125
+ return self.__wait_traj_op(timeout, trans_id, filename, 'Save')
126
+
127
+ def __wait_play_traj(self, timeout, trans_id, times=1):
128
+ if self._support_feedback and trans_id > 0:
129
+ code, feedback_code = self._wait_feedback(timeout, trans_id)
130
+ if feedback_code == XCONF.FeedbackCode.FAILURE:
131
+ code = APIState.TRAJ_PLAYBACK_FAILED
132
+ else:
133
+ start_time = time.monotonic()
134
+ while self.state != 1:
135
+ if self.state in [4]:
136
+ return APIState.STATE_NOT_READY
137
+ if time.monotonic() - start_time > 5:
138
+ return APIState.TRAJ_PLAYBACK_TOUT
139
+ time.sleep(0.1)
140
+ max_count = int((time.monotonic() - start_time) / 0.1)
141
+ max_count = max_count if max_count > 10 else 10
142
+ start_time = time.monotonic()
143
+ while self.mode != 11:
144
+ if self.state == 1:
145
+ start_time = time.monotonic()
146
+ time.sleep(0.1)
147
+ continue
148
+ if self.state in [4]:
149
+ return APIState.STATE_NOT_READY
150
+ if time.monotonic() - start_time > 5:
151
+ return APIState.TRAJ_PLAYBACK_TOUT
152
+ time.sleep(0.1)
153
+ time.sleep(0.1)
154
+ count = 0
155
+ while self.state not in [4]:
156
+ if self.state == 2:
157
+ if times == 1:
158
+ break
159
+ count += 1
160
+ else:
161
+ count = 0
162
+ if count > max_count:
163
+ break
164
+ time.sleep(0.1)
165
+ code = 0 if self.state != 4 else APIState.STATE_NOT_READY
166
+
167
+ if self.state not in [4]:
168
+ self.set_mode(0)
169
+ self.set_state(0)
170
+ self._sync()
171
+ return code
172
+
173
+ @xarm_is_connected(_type='set')
174
+ def load_trajectory(self, filename, wait=True, timeout=None, **kwargs):
175
+ assert isinstance(filename, str) and filename.strip()
176
+ filename = filename.strip()
177
+ if not filename.endswith('.traj'):
178
+ full_filename = '{}.traj'.format(filename)
179
+ else:
180
+ full_filename = filename
181
+ self.get_trajectory_rw_status()
182
+ feedback_key, studio_wait = self._gen_feedback_key(wait, **kwargs)
183
+ ret = self.arm_cmd.load_traj(full_filename, wait_time=0, feedback_key=feedback_key)
184
+ trans_id = self._get_feedback_transid(feedback_key, studio_wait)
185
+ self.log_api_info('API -> load_trajectory -> code={}'.format(ret[0]), code=ret[0])
186
+ if ret[0] == 0 and wait:
187
+ return self.__wait_load_traj(timeout, trans_id, filename)
188
+ if ret[0] != 0:
189
+ logger.error('Load {} failed, ret={}'.format(filename, ret))
190
+ return ret[0]
191
+
192
+ @xarm_is_connected(_type='set')
193
+ def playback_trajectory(self, times=1, filename=None, wait=False, double_speed=1, **kwargs):
194
+ assert isinstance(times, int)
195
+ times = times if times > 0 else -1
196
+ if isinstance(filename, str) and filename.strip():
197
+ ret = self.load_trajectory(filename, wait=True, timeout=None)
198
+ if ret != 0:
199
+ return ret
200
+ if self.state in [4]:
201
+ return APIState.NOT_READY
202
+ feedback_key, studio_wait = self._gen_feedback_key(wait, **kwargs)
203
+ if self.version_is_ge(1, 2, 11):
204
+ ret = self.arm_cmd.playback_traj(times, double_speed, feedback_key=feedback_key)
205
+ else:
206
+ ret = self.arm_cmd.playback_traj_old(times)
207
+ trans_id = self._get_feedback_transid(feedback_key, studio_wait)
208
+ self.log_api_info('API -> playback_trajectory -> code={}'.format(ret[0]), code=ret[0])
209
+ if ret[0] == 0 and wait:
210
+ return self.__wait_play_traj(None, trans_id, times)
211
+ return ret[0]
212
+
213
+ @xarm_is_connected(_type='get')
214
+ def get_trajectory_rw_status(self):
215
+ ret = self.arm_cmd.get_traj_rw_status()
216
+ return ret[0], ret[1]
xarm/x3/report.py ADDED
@@ -0,0 +1,204 @@
1
+ from xarm.core.utils import convert
2
+
3
+
4
+ class ReportHandler(object):
5
+ def __init__(self, report_type):
6
+ self.buffer = b''
7
+ self.report_size = 0
8
+ self.report_type = report_type
9
+ if self.report_type == 'devlop':
10
+ self.parse_handler = self._parse_report_tcp_develop_data
11
+ elif self.report_type == 'normal':
12
+ self.parse_handler = self._parse_report_tcp_normal_data
13
+ elif self.report_type == 'rich':
14
+ self.parse_handler = self._parse_report_tcp_rich_data
15
+ else:
16
+ self.parse_handler = None
17
+ self.source_data = b''
18
+ self.parse_dict = {}
19
+
20
+ def reset(self):
21
+ self.buffer = b''
22
+ self.report_size = 0
23
+
24
+ def process_report_data(self, recv_data):
25
+ if recv_data == -1:
26
+ return
27
+ self.buffer += recv_data
28
+ if len(self.buffer) < 4:
29
+ return
30
+ if self.report_size == 0:
31
+ self.report_size = convert.bytes_to_u32(self.buffer[:4])
32
+ if len(self.buffer) < self.report_size:
33
+ return
34
+ if self.report_type == 'rich' and self.report_size == 233 and len(self.buffer) >= 245:
35
+ # 兼容某几版固件上报的数据的数据长度和实际数据的长度不一致
36
+ try:
37
+ if len(self.buffer) >= 249:
38
+ if convert.bytes_to_u32(self.buffer[245:249]) != self.report_size:
39
+ if convert.bytes_to_u32(self.buffer[233:237]) == self.report_size:
40
+ data = self.buffer[:self.report_size]
41
+ self.buffer = self.buffer[self.report_size:]
42
+ else:
43
+ self.reset()
44
+ # TODO reconnect
45
+ return -1
46
+ else:
47
+ data = self.buffer[:245]
48
+ self.buffer = self.buffer[245:]
49
+ else:
50
+ if convert.bytes_to_u32(self.buffer[233:237]) != self.report_size:
51
+ data = self.buffer[:245]
52
+ self.buffer = self.buffer[245:]
53
+ else:
54
+ data = self.buffer[:self.report_size]
55
+ self.buffer = self.buffer[self.report_size:]
56
+ except:
57
+ self.reset()
58
+ # TODO reconnect
59
+ return -1
60
+ else:
61
+ data = self.buffer[:self.report_size]
62
+ self.buffer = self.buffer[self.report_size:]
63
+ self.source_data = data
64
+ if self.parse_handler:
65
+ return self.parse_handler(data)
66
+
67
+ def __parse_report_common_data(self, rx_data):
68
+ # length = convert.bytes_to_u32(rx_data[0:4])
69
+ length = len(rx_data)
70
+ state, mode = rx_data[4] & 0x0F, rx_data[4] >> 4
71
+ cmd_num = convert.bytes_to_u16(rx_data[5:7])
72
+ angles = convert.bytes_to_fp32s(rx_data[7:7 * 4 + 7], 7)
73
+ pose = convert.bytes_to_fp32s(rx_data[35:6 * 4 + 35], 6)
74
+ torque = convert.bytes_to_fp32s(rx_data[59:7 * 4 + 59], 7)
75
+ self.parse_dict['length'] = length
76
+ self.parse_dict['state'] = state
77
+ self.parse_dict['mode'] = mode
78
+ self.parse_dict['cmd_num'] = cmd_num
79
+ self.parse_dict['angles'] = angles
80
+ self.parse_dict['pose'] = pose
81
+ self.parse_dict['torque'] = torque
82
+ return [length, state, mode, cmd_num, angles, pose, torque]
83
+
84
+ def _parse_report_tcp_develop_data(self, rx_data):
85
+ ret = self.__parse_report_common_data(rx_data)
86
+ return ret
87
+
88
+ def _parse_report_tcp_normal_data(self, rx_data):
89
+ ret = self.__parse_report_common_data(rx_data)
90
+ mtbrake, mtable, error_code, warn_code = rx_data[87:91]
91
+ tcp_offset = convert.bytes_to_fp32s(rx_data[91:6 * 4 + 91], 6)
92
+ tcp_load = convert.bytes_to_fp32s(rx_data[115:4 * 4 + 115], 4)
93
+ collis_sens, teach_sens = rx_data[131:133]
94
+ gravity_direction = convert.bytes_to_fp32s(rx_data[133:3 * 4 + 133], 3)
95
+ mtbrake = [mtbrake & 0x01, mtbrake >> 1 & 0x01, mtbrake >> 2 & 0x01, mtbrake >> 3 & 0x01,
96
+ mtbrake >> 4 & 0x01, mtbrake >> 5 & 0x01, mtbrake >> 6 & 0x01, mtbrake >> 7 & 0x01]
97
+ mtable = [mtable & 0x01, mtable >> 1 & 0x01, mtable >> 2 & 0x01, mtable >> 3 & 0x01,
98
+ mtable >> 4 & 0x01, mtable >> 5 & 0x01, mtable >> 6 & 0x01, mtable >> 7 & 0x01]
99
+ self.parse_dict['mtbrake'] = mtbrake
100
+ self.parse_dict['mtable'] = mtable
101
+ self.parse_dict['tcp_offset'] = tcp_offset
102
+ self.parse_dict['tcp_load'] = tcp_load
103
+ self.parse_dict['error_code'] = error_code
104
+ self.parse_dict['warn_code'] = warn_code
105
+ self.parse_dict['collis_sens'] = collis_sens
106
+ self.parse_dict['teach_sens'] = teach_sens
107
+ self.parse_dict['gravity_direction'] = gravity_direction
108
+ ret.extend([mtbrake, mtable, error_code, warn_code, tcp_offset, tcp_load, collis_sens, teach_sens, gravity_direction])
109
+ return ret
110
+
111
+ def _parse_report_tcp_rich_data(self, rx_data):
112
+ ret = self._parse_report_tcp_normal_data(rx_data)
113
+ length = ret[0]
114
+ if length >= 151:
115
+ arm_type, arm_axis, arm_master_id, arm_slave_id, arm_motor_tid, arm_motor_fid = rx_data[145:151]
116
+ self.parse_dict['arm_type'] = arm_type
117
+ self.parse_dict['arm_axis'] = arm_axis
118
+ self.parse_dict['arm_master_id'] = arm_master_id
119
+ self.parse_dict['arm_slave_id'] = arm_slave_id
120
+ self.parse_dict['arm_motor_tid'] = arm_motor_tid
121
+ self.parse_dict['arm_motor_fid'] = arm_motor_fid
122
+ ret.extend([arm_type, arm_axis, arm_master_id, arm_slave_id, arm_motor_tid, arm_motor_fid])
123
+ if length >= 181:
124
+ version = str(rx_data[151:180], 'utf-8')
125
+ self.parse_dict['version'] = version
126
+ ret.append(version)
127
+ if length >= 201:
128
+ trs_msg = convert.bytes_to_fp32s(rx_data[181:201], 5)
129
+ tcp_jerk, min_tcp_acc, max_tcp_acc, min_tcp_speed, max_tcp_speed = trs_msg
130
+ self.parse_dict['tcp_jerk'] = tcp_jerk
131
+ self.parse_dict['min_tcp_acc'] = min_tcp_acc
132
+ self.parse_dict['max_tcp_acc'] = max_tcp_acc
133
+ self.parse_dict['min_tcp_speed'] = min_tcp_speed
134
+ self.parse_dict['max_tcp_speed'] = max_tcp_speed
135
+ ret.extend([tcp_jerk, min_tcp_acc, max_tcp_acc, min_tcp_speed, max_tcp_speed])
136
+ if length >= 221:
137
+ p2p_msg = convert.bytes_to_fp32s(rx_data[201:221], 5)
138
+ joint_jerk, min_joint_acc, max_joint_acc, min_joint_speed, max_joint_speed = p2p_msg
139
+ self.parse_dict['joint_jerk'] = joint_jerk
140
+ self.parse_dict['min_joint_acc'] = min_joint_acc
141
+ self.parse_dict['max_joint_acc'] = max_joint_acc
142
+ self.parse_dict['min_joint_speed'] = min_joint_speed
143
+ self.parse_dict['max_joint_speed'] = max_joint_speed
144
+ ret.extend([joint_jerk, min_joint_acc, max_joint_acc, min_joint_speed, max_joint_speed])
145
+ if length >= 229:
146
+ rot_msg = convert.bytes_to_fp32s(rx_data[221:229], 2)
147
+ rot_jerk, max_rot_acc = rot_msg
148
+ self.parse_dict['rot_jerk'] = rot_jerk
149
+ self.parse_dict['max_rot_acc'] = max_rot_acc
150
+ ret.extend([rot_jerk, max_rot_acc])
151
+ if length >= 245:
152
+ servo_code = [val for val in rx_data[229:245]]
153
+ self.parse_dict['servo_code'] = servo_code
154
+ ret.extend([servo_code[:-2], servo_code[-2:]])
155
+ if length >= 252:
156
+ temperatures = list(map(int, rx_data[245:252]))
157
+ self.parse_dict['temperatures'] = temperatures
158
+ ret.append(temperatures)
159
+ if length >= 284:
160
+ speeds = convert.bytes_to_fp32s(rx_data[252:8 * 4 + 252], 8)
161
+ self.parse_dict['speeds'] = speeds
162
+ ret.append(speeds)
163
+ if length >= 288:
164
+ count = convert.bytes_to_u32(rx_data[284:288])
165
+ self.parse_dict['count'] = count
166
+ ret.append(count)
167
+ if length >= 312:
168
+ world_offset = convert.bytes_to_fp32s(rx_data[288:6 * 4 + 288], 6)
169
+ self.parse_dict['world_offset'] = world_offset
170
+ ret.append(world_offset)
171
+ if length >= 314:
172
+ cgpio_reset_enable, tgpio_reset_enable = rx_data[312:314]
173
+ self.parse_dict['cgpio_reset_enable'] = cgpio_reset_enable
174
+ self.parse_dict['tgpio_reset_enable'] = tgpio_reset_enable
175
+ ret.extend([cgpio_reset_enable, tgpio_reset_enable])
176
+ if length >= 416:
177
+ # if length >= 340:
178
+ is_collision_check, collision_tool_type = rx_data[314:316]
179
+ collision_tool_params = convert.bytes_to_fp32s(rx_data[316:340], 6)
180
+ self.parse_dict['is_collision_check'] = is_collision_check
181
+ self.parse_dict['collision_tool_type'] = collision_tool_type
182
+ self.parse_dict['collision_tool_params'] = collision_tool_params
183
+ ret.extend([is_collision_check, collision_tool_type, collision_tool_params])
184
+ # if length >= 354:
185
+ voltages = convert.bytes_to_u16s(rx_data[340:354], 7)
186
+ voltages = list(map(lambda x: x / 100, voltages))
187
+ self.parse_dict['voltages'] = voltages
188
+ ret.append(voltages)
189
+ # if length >= 382:
190
+ currents = convert.bytes_to_fp32s(rx_data[354:382], 7)
191
+ self._currents = currents
192
+ self.parse_dict['currents'] = currents
193
+ ret.append(currents)
194
+ # if length >= 416:
195
+ cgpio_states = []
196
+ cgpio_states.extend(rx_data[382:384])
197
+ cgpio_states.extend(convert.bytes_to_u16s(rx_data[384:400], 8))
198
+ cgpio_states[6:10] = list(map(lambda x: x / 4095.0 * 10.0, cgpio_states[6:10]))
199
+ cgpio_states.append(list(map(int, rx_data[400:408])))
200
+ cgpio_states.append(list(map(int, rx_data[408:416])))
201
+ self.parse_dict['cgpio_states'] = cgpio_states
202
+ ret.append(cgpio_states)
203
+ return ret
204
+