Skip to content

Commit b062644

Browse files
committed
refactor: imporve api
1 parent 7832109 commit b062644

File tree

2 files changed

+135
-68
lines changed

2 files changed

+135
-68
lines changed

pymycobot/common.py

Lines changed: 52 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ class Command():
99
FOOTER = 0xfa
1010

1111
# Overall status
12+
VERSION = 0x00
1213
POWER_ON = 0x10
1314
POWER_OFF = 0x11
1415
IS_POWER_ON = 0x12
@@ -89,6 +90,56 @@ def _flatten(self, _list):
8990
return sum(([x] if not isinstance(x, list) else self._flatten(x)
9091
for x in _list), [])
9192

93+
def _process_data_command(self, args):
94+
if not args:
95+
return []
96+
97+
return self._flatten([
98+
[self._encode_int16(i) for i in x]
99+
if isinstance(x, list) else x
100+
for x in args])
101+
102+
def _is_frame_header(self, data, pos):
103+
return data[pos] == Command.HEADER and data[pos + 1] == Command.HEADER
104+
105+
def _process_recived(self, data, genre):
106+
if not data:
107+
return []
108+
109+
data = bytearray(data)
110+
data_len = len(data)
111+
# Get valid header: 0xfe0xfe
112+
for idx in range(data_len - 1):
113+
if self._is_frame_header(data, idx):
114+
break
115+
else:
116+
return []
117+
118+
data_len = data[idx + 2] - 2
119+
120+
# compare send header and received header
121+
cmd_id = data[idx + 3]
122+
if cmd_id != genre:
123+
return []
124+
data_pos = idx + 4
125+
valid_data = (data[data_pos:data_pos + data_len])
126+
127+
# process valid data
128+
res = []
129+
if data_len == 12:
130+
for idx in range(0, len(valid_data), 2):
131+
one = valid_data[idx:idx + 2]
132+
res.append(self._decode_int16(one))
133+
elif data_len == 2:
134+
res.append(self._decode_int16(valid_data))
135+
else:
136+
res.append(self._decode_int8(valid_data))
137+
return res
138+
139+
def _process_single(self, data):
140+
return data[0] if data else -1
141+
142+
'''
92143
def _process_data_command(self, data, genre):
93144
# lenght = 0
94145
if not data:
@@ -133,41 +184,4 @@ def _process_data_command(self, data, genre):
133184
# lenght = 1
134185
else:
135186
return [data[0]]
136-
137-
def _is_frame_header(self, data, pos):
138-
return data[pos] == Command.HEADER and data[pos + 1] == Command.HEADER
139-
140-
def _process_recived(self, data, genre):
141-
if not data:
142-
return []
143-
144-
data = bytearray(data)
145-
data_len = len(data)
146-
for idx in range(data_len - 1):
147-
if self._is_frame_header(data, idx):
148-
break
149-
else:
150-
return []
151-
152-
data_len = data[idx + 2] - 2
153-
cmd_id = data[idx + 3]
154-
if cmd_id != genre:
155-
return []
156-
data_pos = idx + 4
157-
valid_data = (data[data_pos:data_pos + data_len])
158-
# print(data_len)
159-
# print(valid_data)
160-
161-
res = []
162-
if data_len == 12:
163-
for idx in range(0, len(valid_data), 2):
164-
one = valid_data[idx:idx + 2]
165-
res.append(self._decode_int16(one))
166-
elif data_len == 2:
167-
res.append(self._decode_int16(valid_data))
168-
else:
169-
res.append(self._decode_int8(valid_data))
170-
return res
171-
172-
def _process_single(self, data):
173-
return data[0] if data else -1
187+
'''

pymycobot/mycobot.py

Lines changed: 83 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class MyCobot(MyCobotData):
1212
Possessed function:
1313
1414
# Overall status
15+
version()
1516
power_on()
1617
power_off()
1718
is_power_on()
@@ -64,8 +65,17 @@ class MyCobot(MyCobotData):
6465
is_gripper_moving()
6566
'''
6667

67-
def __init__(self, port, boudrate='115200', timeout=0.1):
68+
def __init__(self, port, boudrate='115200', timeout=0.1, debug=False):
69+
'''
70+
Args:
71+
port : port string
72+
boudrate : baud rate string, default '115200'
73+
timeout : default 0.1
74+
debug : whether show debug info
75+
76+
'''
6877
self._version = sys.version_info[:2][0]
78+
self.debug = debug
6979
for _ in range(5):
7080
try:
7181
self._serial_port = serial.Serial(port,
@@ -80,7 +90,12 @@ def __init__(self, port, boudrate='115200', timeout=0.1):
8090
print('Connect prot failed, eixt.')
8191
exit(0)
8292

93+
def _debug_log(self, info, _type=None):
94+
print('[debug] {}: {}'.format(_type, info))
95+
8396
def _write(self, command):
97+
if self.debug:
98+
self._debug_log(command, 'serial will write')
8499
self._serial_port.write(command)
85100
self._serial_port.flush()
86101
time.sleep(0.05)
@@ -89,24 +104,52 @@ def _read(self, size=1024):
89104
if self._serial_port.inWaiting() > 0:
90105
data = self._serial_port.read(self._serial_port.inWaiting())
91106
else:
107+
if self.debug:
108+
self._debug_log('no data can be read', 'warn')
92109
data = None
93110
return data
94111

95-
def __mesg(self, genre, data=None, has_reply=False):
96-
command_data = self._process_data_command(data, genre)
112+
def __mesg(self, genre, *args, **kwargs):
113+
'''
114+
115+
Args:
116+
genre: command type (Command)
117+
*args: other data.
118+
It is converted to octal by default.
119+
If the data needs to be encapsulated into hexadecimal,
120+
the array is used to include them. (Data cannot be nested)
121+
**kwargs: support `has_reply`
122+
has_reply: Whether there is a return value to accept.
123+
124+
'''
125+
command_data = self._process_data_command(args)
126+
if self.debug:
127+
self._debug_log(command_data, 'processed data')
128+
97129
LEN = len(command_data) + 2
98130
command = [
99131
Command.HEADER, Command.HEADER, LEN, genre, command_data,
100132
Command.FOOTER
101133
]
102134
self._write(self._flatten(command))
103135

104-
if has_reply:
136+
if 'has_reply' in kwargs and kwargs['has_reply']:
105137
data = self._read()
106138
res = self._process_recived(data, genre)
107139
return res
108140

109141
# Overall status
142+
def version(self): # TODO: test method <11-03-21, yourname> #
143+
'''Get cobot verion
144+
145+
Return:
146+
mycobot : 1
147+
mycobotPro: 101
148+
149+
'''
150+
recv = self.__mesg(Command.VERSION, has_reply=True)
151+
return recv
152+
110153
def power_on(self):
111154
self.__mesg(Command.POWER_ON)
112155

@@ -150,8 +193,8 @@ def send_angle(self, id, degree, speed):
150193
speed (int): 0 ~100
151194
152195
'''
153-
data = [id - 1, self._angle_to_int(degree), speed]
154-
self.__mesg(Command.SEND_ANGLE, data=data)
196+
self.__mesg(Command.SEND_ANGLE, id - 1, [self._angle_to_int(degree)],
197+
speed)
155198

156199
def send_angles(self, degrees, speed):
157200
'''Send all angles
@@ -162,8 +205,8 @@ def send_angles(self, degrees, speed):
162205
163206
'''
164207
degrees = [self._angle_to_int(degree) for degree in degrees]
165-
data = [degrees, speed]
166-
self.__mesg(Command.SEND_ANGLES, data=self._flatten(data))
208+
# data = [degrees, speed]
209+
self.__mesg(Command.SEND_ANGLES, degrees, speed)
167210

168211
def get_radians(self):
169212
'''Get all angle return a list
@@ -189,8 +232,7 @@ def send_radians(self, radians, speed):
189232
degrees = [
190233
self._angle_to_int(radian * (180 / math.pi)) for radian in radians
191234
]
192-
return self.__mesg(Command.SEND_ANGLES,
193-
data=self._flatten([degrees, speed]))
235+
return self.__mesg(Command.SEND_ANGLES, degrees, speed)
194236

195237
def get_coords(self):
196238
'''Get all coords.
@@ -220,9 +262,8 @@ def send_coord(self, id, coord, speed):
220262
speed(int):
221263
222264
'''
223-
return self.__mesg(Command.SEND_COORD,
224-
data=[id - 1,
225-
self._coord_to_int(coord), speed])
265+
return self.__mesg(Command.SEND_COORD, id - 1,
266+
[self._coord_to_int(coord)], speed)
226267

227268
def send_coords(self, coords, speed, mode):
228269
'''Send all coords
@@ -241,8 +282,7 @@ def send_coords(self, coords, speed, mode):
241282
coord_list.append(self._coord_to_int(coords[idx]))
242283
for idx in range(3, 6):
243284
coord_list.append(self._angle_to_int(coords[idx]))
244-
self.__mesg(Command.SEND_COORDS,
245-
data=self._flatten([coord_list, speed, mode]))
285+
self.__mesg(Command.SEND_COORDS, coord_list, speed, mode)
246286

247287
def pause(self):
248288
self.__mesg(Command.PAUSE)
@@ -283,8 +323,9 @@ def is_in_position(self, data, id):
283323
raise MyCobotDataException("id is not right, please input 0 or 1")
284324

285325
received = self.__mesg(Command.IS_IN_POSITION,
286-
data=data_list,
287-
has_reply=True)
326+
data_list,
327+
id,
328+
has_reply=True)
288329
return self._process_single(received)
289330

290331
def is_moving(self):
@@ -308,7 +349,7 @@ def jog_angle(self, joint_id, direction, speed):
308349
direction: int [0, 1]
309350
speed: int (0 - 100)
310351
'''
311-
self.__mesg(Command.JOG_ANGLE, data=[joint_id, direction, speed])
352+
self.__mesg(Command.JOG_ANGLE, joint_id, direction, speed)
312353

313354
@check_id
314355
def jog_coord(self, coord_id, direction, speed):
@@ -319,7 +360,7 @@ def jog_coord(self, coord_id, direction, speed):
319360
direction: int [0, 1]
320361
speed: int (0 - 100)
321362
'''
322-
self.__mesg(Command.JOG_COORD, data=[coord_id, direction, speed])
363+
self.__mesg(Command.JOG_COORD, coord_id, direction, speed)
323364

324365
def jog_stop(self):
325366
self.__mesg(Command.JOG_STOP)
@@ -339,27 +380,27 @@ def set_speed(self, speed):
339380
raise MyCobotDataException(
340381
'speed value not right, should be 0 ~ 100 ')
341382

342-
self.__mesg(Command.SET_SPEED, data=[speed])
383+
self.__mesg(Command.SET_SPEED, speed)
343384

344385
@check_id
345386
def get_joint_min_angle(self, joint_id):
346387
angle = self.__mesg(Command.GET_JOINT_MIN_ANGLE,
347-
data=[joint_id],
388+
joint_id,
348389
has_reply=True)
349390
return self._int_to_angle(angle[0]) if angle else 0
350391

351392
@check_id
352393
def get_joint_max_angle(self, joint_id):
353394
angle = self.__mesg(Command.GET_JOINT_MAX_ANGLE,
354-
data=[joint_id],
395+
joint_id,
355396
has_reply=True)
356397
return self._int_to_angle(angle[0]) if angle else 0
357398

358399
# Servo control
359400
@check_id
360401
def is_servo_enable(self, servo_id):
361402
return self._process_single(
362-
self.__mesg(Command.IS_SERVO_ENABLE, data=[servo_id]))
403+
self.__mesg(Command.IS_SERVO_ENABLE, servo_id))
363404

364405
def is_all_servo_enable(self):
365406
return self._process_single(
@@ -384,6 +425,18 @@ def focus_servo(self, servo_id):
384425
self.__mesg(Command.RELEASE_SERVO, servo_id)
385426

386427
# Atom IO
428+
def set_color(self, r, g, b):
429+
'''Set the light color
430+
431+
Args:
432+
rgs (str): example 'ff0000'
433+
r (int): 0 ~ 255
434+
g (int): 0 ~ 255
435+
b (int): 0 ~ 255
436+
437+
'''
438+
self.__mesg(Command.SET_COLOR, r, g, b)
439+
387440
def set_led_color(self, rgb):
388441
'''Set the light color
389442
@@ -413,7 +466,7 @@ def set_pin_mode(self, pin_no, pin_mode):
413466
pin_mode (int): 0 - input, 1 - output, 2 - input_pullup
414467
415468
'''
416-
self.__mesg(Command.SET_PIN_MODE, data=[pin_no, pin_mode])
469+
self.__mesg(Command.SET_PIN_MODE, pin_no, pin_mode)
417470

418471
def set_digital_output(self, pin_no, pin_signal):
419472
'''
@@ -423,19 +476,19 @@ def set_digital_output(self, pin_no, pin_signal):
423476
pin_signal (int): 0 / 1
424477
425478
'''
426-
self.__mesg(Command.SET_DIGITAL_OUTPUT, data=[pin_no, pin_signal])
479+
self.__mesg(Command.SET_DIGITAL_OUTPUT, pin_no, pin_signal)
427480

428481
def get_digital_input(self, pin_no):
429482
return self._process_single(
430483
self.__mesg(Command.GET_DIGITAL_INPUT,
431-
data=[pin_no],
484+
pin_no,
432485
has_reply=True))
433486

434487
def set_pwm_mode(self, pin_no, channel):
435-
self.__mesg(Command.SET_PWM_MODE, data=[pin_no, channel])
488+
self.__mesg(Command.SET_PWM_MODE, pin_no, channel)
436489

437490
def set_pwm_output(self, channel, pin_val):
438-
self.__mesg(Command.SET_PWM_OUTPUT, data=[channel, pin_val])
491+
self.__mesg(Command.SET_PWM_OUTPUT, channel, pin_val)
439492

440493
def get_gripper_value(self):
441494
return self._process_single(
@@ -452,7 +505,7 @@ def set_gripper_state(self, flag, speed):
452505
if not flag in [0, 1]:
453506
raise MyCobotDataException('eror flag, please input 0 or 1')
454507

455-
self.__mesg(Command.SET_GRIPPER_STATE, data=[flag, speed])
508+
self.__mesg(Command.SET_GRIPPER_STATE, flag, speed)
456509

457510
def set_gripper_value(self, value, speed):
458511
'''Set gripper value
@@ -462,7 +515,7 @@ def set_gripper_value(self, value, speed):
462515
speed (int): 0 ~ 100
463516
464517
'''
465-
self.__mesg(Command.SET_GRIPPER_VALUE, data=[value, speed])
518+
self.__mesg(Command.SET_GRIPPER_VALUE, value, speed)
466519

467520
def set_gripper_ini(self):
468521
'''Set the current position to zero

0 commit comments

Comments
 (0)