pymycobot 3.5.0.dev4__tar.gz → 3.5.0.dev6__tar.gz
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.
- {pymycobot-3.5.0.dev4/pymycobot.egg-info → pymycobot-3.5.0.dev6}/PKG-INFO +1 -1
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/__init__.py +3 -3
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/common.py +6 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/error.py +4 -4
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/mercury_api.py +71 -31
- pymycobot-3.5.0.dev6/pymycobot/mercurychassis.py +325 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6/pymycobot.egg-info}/PKG-INFO +1 -1
- pymycobot-3.5.0.dev4/pymycobot/mercurychassis.py +0 -170
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/LICENSE +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/MANIFEST.in +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/README.md +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/Interface.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/bluet.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/elephantrobot.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/generate.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/genre.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/log.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/mecharm.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/mecharmsocket.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/mercury.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/mercurysocket.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/myagv.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/myarm.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/myarm_api.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/myarmc.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/myarmm.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/myarmsocket.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/mybuddy.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/mybuddybluetooth.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/mybuddyemoticon.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/mybuddysocket.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/mycobot.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/mycobotpro630.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/mycobotsocket.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/mypalletizer.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/mypalletizersocket.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/progripper.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/public.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/ultraArm.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot/utils.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot.egg-info/SOURCES.txt +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot.egg-info/dependency_links.txt +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot.egg-info/requires.txt +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/pymycobot.egg-info/top_level.txt +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/requirements.txt +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/setup.cfg +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/setup.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/tests/test_api.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/tests/test_generator.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/tests/test_socket.py +0 -0
- {pymycobot-3.5.0.dev4 → pymycobot-3.5.0.dev6}/tests/test_utils.py +0 -0
|
@@ -23,7 +23,7 @@ from pymycobot.elephantrobot import ElephantRobot
|
|
|
23
23
|
from pymycobot.mercury import Mercury
|
|
24
24
|
from pymycobot.myagv import MyAgv
|
|
25
25
|
from pymycobot.mecharmsocket import MechArmSocket
|
|
26
|
-
from pymycobot.mercurychassis import
|
|
26
|
+
from pymycobot.mercurychassis import ChassisControl
|
|
27
27
|
from pymycobot.mercurysocket import MercurySocket
|
|
28
28
|
from pymycobot.mycobotpro630 import Phoenix
|
|
29
29
|
from pymycobot.myarmm import MyArmM
|
|
@@ -49,7 +49,7 @@ __all__ = [
|
|
|
49
49
|
"MyAgv",
|
|
50
50
|
"MechArmSocket",
|
|
51
51
|
"MyArmSocket",
|
|
52
|
-
"
|
|
52
|
+
"ChassisControl",
|
|
53
53
|
"MercurySocket",
|
|
54
54
|
"Phoenix",
|
|
55
55
|
"MyArmM",
|
|
@@ -61,7 +61,7 @@ if sys.platform == "linux":
|
|
|
61
61
|
from pymycobot.mybuddyemoticon import MyBuddyEmoticon
|
|
62
62
|
__all__.append("MyBuddyEmoticon")
|
|
63
63
|
|
|
64
|
-
__version__ = "3.5.
|
|
64
|
+
__version__ = "3.5.0dev6"
|
|
65
65
|
__author__ = "Elephantrobotics"
|
|
66
66
|
__email__ = "weiquan.xu@elephantrobotics.com"
|
|
67
67
|
__git_url__ = "https://github.com/elephantrobotics/pymycobot"
|
|
@@ -22,9 +22,15 @@ class ProtocolCode(object):
|
|
|
22
22
|
CLEAR_ERROR_INFO = 0x08
|
|
23
23
|
GET_ATOM_VERSION = 0x09
|
|
24
24
|
|
|
25
|
+
CLEAR_ZERO_POS = 0x0A
|
|
26
|
+
SET_SERVO_CW = 0x0B
|
|
27
|
+
GET_SERVO_CW = 0x0C
|
|
28
|
+
CLEAR_WAIST_QUEUE = 0x0D
|
|
29
|
+
|
|
25
30
|
SetHTSGripperTorque = 0x35
|
|
26
31
|
GetHTSGripperTorque = 0x36
|
|
27
32
|
GetGripperProtectCurrent = 0x37
|
|
33
|
+
JOG_INCREMENT_BASE_COORD = 0x37
|
|
28
34
|
InitGripper = 0x38
|
|
29
35
|
SetGripperProtectCurrent = 0x39
|
|
30
36
|
|
|
@@ -238,15 +238,15 @@ def calibration_parameters(**kwargs):
|
|
|
238
238
|
robot_limit = {
|
|
239
239
|
"Mercury": {
|
|
240
240
|
"id": [1, 2, 3, 4, 5, 6, 11, 12, 13],
|
|
241
|
-
"angles_min": [-165, -55, -
|
|
242
|
-
"angles_max": [165, 95, 5, 165,
|
|
241
|
+
"angles_min": [-165, -55, -173, -165, -20, -180, -60, -138, -118],
|
|
242
|
+
"angles_max": [165, 95, 5, 165, 265, 180, 0, 188, 118],
|
|
243
243
|
"coords_min": [-441.37, -441.37, -206.52, -180, -180, -180],
|
|
244
244
|
"coords_max": [441.37, 441.37, 628.02, 180, 180, 180]
|
|
245
245
|
},
|
|
246
246
|
"MercurySocket": {
|
|
247
247
|
"id": [1, 2, 3, 4, 5, 6, 11, 12, 13],
|
|
248
|
-
"angles_min": [-165, -55, -
|
|
249
|
-
"angles_max": [165, 95, 5, 165,
|
|
248
|
+
"angles_min": [-165, -55, -173, -165, -20, -180, -60, -138, -118],
|
|
249
|
+
"angles_max": [165, 95, 5, 165, 265, 180, 0, 188, 118],
|
|
250
250
|
"coords_min": [-441.37, -441.37, -206.52, -180, -180, -180],
|
|
251
251
|
"coords_max": [441.37, 441.37, 628.02, 180, 180, 180]
|
|
252
252
|
},
|
|
@@ -61,21 +61,21 @@ class MercuryCommandGenerator(CommandGenerator):
|
|
|
61
61
|
elif genre in [ProtocolCode.POWER_OFF, ProtocolCode.RELEASE_ALL_SERVOS, ProtocolCode.FOCUS_ALL_SERVOS,
|
|
62
62
|
ProtocolCode.RELEASE_SERVO, ProtocolCode.FOCUS_SERVO, ProtocolCode.STOP]:
|
|
63
63
|
wait_time = 3
|
|
64
|
-
elif genre in [
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
64
|
+
# elif genre in [
|
|
65
|
+
# ProtocolCode.SEND_ANGLE,
|
|
66
|
+
# ProtocolCode.SEND_ANGLES,
|
|
67
|
+
# ProtocolCode.SEND_COORD,
|
|
68
|
+
# ProtocolCode.SEND_COORDS,
|
|
69
|
+
# ProtocolCode.JOG_ANGLE,
|
|
70
|
+
# ProtocolCode.JOG_COORD,
|
|
71
|
+
# ProtocolCode.JOG_INCREMENT,
|
|
72
|
+
# ProtocolCode.JOG_INCREMENT_COORD,
|
|
73
|
+
# ProtocolCode.COBOTX_SET_SOLUTION_ANGLES,
|
|
74
|
+
# ProtocolCode.MERCURY_SET_BASE_COORDS,
|
|
75
|
+
# ProtocolCode.MERCURY_JOG_BASE_COORD,
|
|
76
|
+
# ProtocolCode.MERCURY_SET_BASE_COORD]:
|
|
77
|
+
# wait_time = 300
|
|
78
|
+
# is_in_position = True
|
|
79
79
|
need_break = False
|
|
80
80
|
data = None
|
|
81
81
|
while True and time.time() - t < wait_time:
|
|
@@ -181,18 +181,18 @@ class MercuryCommandGenerator(CommandGenerator):
|
|
|
181
181
|
one = valid_data[i : i + 2]
|
|
182
182
|
res.append(self._decode_int16(one))
|
|
183
183
|
i+=2
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
184
|
+
elif data_len == 30:
|
|
185
|
+
# right arm get_robot_status
|
|
186
|
+
i = 0
|
|
187
|
+
res = []
|
|
188
|
+
while i < data_len:
|
|
189
|
+
if i < 8 or i >= 24:
|
|
190
|
+
res.append(valid_data[i])
|
|
191
|
+
i+=1
|
|
192
|
+
elif i < 23:
|
|
193
|
+
one = valid_data[i : i + 2]
|
|
194
|
+
res.append(self._decode_int16(one))
|
|
195
|
+
i+=2
|
|
196
196
|
elif data_len == 48:
|
|
197
197
|
# get_pos_over
|
|
198
198
|
for i in range(0, data_len, 8):
|
|
@@ -297,7 +297,7 @@ class MercuryCommandGenerator(CommandGenerator):
|
|
|
297
297
|
if res[i] == 1:
|
|
298
298
|
r.append(i)
|
|
299
299
|
return r
|
|
300
|
-
elif genre in [ProtocolCode.COBOTX_GET_ANGLE, ProtocolCode.COBOTX_GET_SOLUTION_ANGLES, ProtocolCode.MERCURY_GET_POS_OVER_SHOOT]:
|
|
300
|
+
elif genre in [ProtocolCode.COBOTX_GET_ANGLE, ProtocolCode.COBOTX_GET_SOLUTION_ANGLES, ProtocolCode.MERCURY_GET_POS_OVER_SHOOT, ProtocolCode.GET_SERVO_CW]:
|
|
301
301
|
return self._int2angle(res[0])
|
|
302
302
|
elif genre == ProtocolCode.MERCURY_ROBOT_STATUS:
|
|
303
303
|
if len(res) == 23:
|
|
@@ -437,8 +437,9 @@ class MercuryCommandGenerator(CommandGenerator):
|
|
|
437
437
|
for d in datas:
|
|
438
438
|
command_log += hex(d)[2:] + " "
|
|
439
439
|
self.log.debug("_read : {}".format(command_log))
|
|
440
|
-
|
|
441
|
-
self.
|
|
440
|
+
if res != []:
|
|
441
|
+
with self.lock:
|
|
442
|
+
self.read_command.append(res)
|
|
442
443
|
# return datas
|
|
443
444
|
|
|
444
445
|
def set_solution_angles(self, angle, speed):
|
|
@@ -1022,4 +1023,43 @@ class MercuryCommandGenerator(CommandGenerator):
|
|
|
1022
1023
|
5 : Drag teaching sampling period
|
|
1023
1024
|
value (int): Filter length, range is 1 ~ 100
|
|
1024
1025
|
"""
|
|
1025
|
-
return self._mesg(ProtocolCode.SET_FILTER_LEN, rank, value)
|
|
1026
|
+
return self._mesg(ProtocolCode.SET_FILTER_LEN, rank, value)
|
|
1027
|
+
|
|
1028
|
+
def clear_zero_pos(self):
|
|
1029
|
+
return self._mesg(ProtocolCode.CLEAR_ZERO_POS)
|
|
1030
|
+
|
|
1031
|
+
def set_servo_cw(self, joint_id, err_angle):
|
|
1032
|
+
"""Set the joint in-place feedback error angle
|
|
1033
|
+
|
|
1034
|
+
Args:
|
|
1035
|
+
joint_id (int): Joint ID, 11 or 12.
|
|
1036
|
+
err_angle (float): Error range is 0 ~ 5.
|
|
1037
|
+
"""
|
|
1038
|
+
return self._mesg(ProtocolCode.SET_SERVO_CW, joint_id, [self._angle2int(err_angle)])
|
|
1039
|
+
|
|
1040
|
+
def get_servo_cw(self, joint_id):
|
|
1041
|
+
"""Get the joint in-place feedback error angle
|
|
1042
|
+
|
|
1043
|
+
Args:
|
|
1044
|
+
joint_id (int): Joint ID, 11 or 12.
|
|
1045
|
+
|
|
1046
|
+
Returns:
|
|
1047
|
+
float: Error angle, range is 0 ~ 5.
|
|
1048
|
+
"""
|
|
1049
|
+
return self._mesg(ProtocolCode.GET_SERVO_CW, joint_id, has_reply=True)
|
|
1050
|
+
|
|
1051
|
+
def clearWaistQueue(self):
|
|
1052
|
+
"""Clear the cache points of the three motors in the torso
|
|
1053
|
+
"""
|
|
1054
|
+
return self._mesg(ProtocolCode.CLEAR_WAIST_QUEUE)
|
|
1055
|
+
|
|
1056
|
+
def jog_increment_base_coord(self, axis, increment, speed):
|
|
1057
|
+
"""Base coordinate stepping control
|
|
1058
|
+
|
|
1059
|
+
Args:
|
|
1060
|
+
axis (int): axis id, range 1 ~ 6 corresponds to [x,y,z,rx,ry,rz]
|
|
1061
|
+
increment (float): Incremental value
|
|
1062
|
+
speed (int): speed
|
|
1063
|
+
"""
|
|
1064
|
+
return self._mesg(ProtocolCode.JOG_INCREMENT_BASE_COORD, axis, [self._angle2int(increment)], speed)
|
|
1065
|
+
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
# -*- coding:utf-8 -*-
|
|
3
|
+
# @File : mercurychassis_api.py
|
|
4
|
+
# @Author : Wang Weijian
|
|
5
|
+
# @Time : 2024/05/31 15:19:47
|
|
6
|
+
# @function: the script is used to do something
|
|
7
|
+
# @version : V1
|
|
8
|
+
import traceback
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
import time
|
|
11
|
+
import serial
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ProtocolCode(object):
|
|
15
|
+
# send data
|
|
16
|
+
header = 0x7B
|
|
17
|
+
footer = 0x7D
|
|
18
|
+
# Ultrasonic data
|
|
19
|
+
ultrasound_header = 0xFA
|
|
20
|
+
ultrasound_footer = 0xFC
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ChassisControl:
|
|
24
|
+
|
|
25
|
+
def __init__(self, port="/dev/wheeltec_controller", baudrate=115200, timeout=0.1, debug=False):
|
|
26
|
+
"""
|
|
27
|
+
Args:
|
|
28
|
+
port : port string
|
|
29
|
+
baudrate : baud rate string, default '115200'
|
|
30
|
+
timeout : default 0.1
|
|
31
|
+
debug : whether show debug info, default: False
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
self._serial_port = serial.Serial()
|
|
35
|
+
self._serial_port.port = port
|
|
36
|
+
self._serial_port.baudrate = baudrate
|
|
37
|
+
self._serial_port.timeout = timeout
|
|
38
|
+
self._serial_port.rts = True
|
|
39
|
+
self._serial_port.dtr = True
|
|
40
|
+
self._serial_port.open()
|
|
41
|
+
self.debug = debug
|
|
42
|
+
self.Send_Data = [0] * 11
|
|
43
|
+
time.sleep(0.2)
|
|
44
|
+
|
|
45
|
+
def _write(self):
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
def _read(self):
|
|
49
|
+
data = b""
|
|
50
|
+
t = time.time()
|
|
51
|
+
time.sleep(0.1)
|
|
52
|
+
if self._serial_port.inWaiting() > 0:
|
|
53
|
+
data = self._serial_port.read(self._serial_port.inWaiting())
|
|
54
|
+
return data
|
|
55
|
+
|
|
56
|
+
def _debug(self, data):
|
|
57
|
+
"""whether show info."""
|
|
58
|
+
hex_data = " ".join(f"{value:02X}" for value in data)
|
|
59
|
+
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
60
|
+
if self.debug:
|
|
61
|
+
print(f"\n***** Debug Info *****\n{current_time} send command: {hex_data}")
|
|
62
|
+
|
|
63
|
+
def close(self):
|
|
64
|
+
self._serial_port.close()
|
|
65
|
+
|
|
66
|
+
def open(self):
|
|
67
|
+
self._serial_port.open()
|
|
68
|
+
|
|
69
|
+
def _request(self, flag=""):
|
|
70
|
+
"""
|
|
71
|
+
Read Data
|
|
72
|
+
:param flag: Data type parameter variable
|
|
73
|
+
:return:
|
|
74
|
+
"""
|
|
75
|
+
receive_all_data = self._read()
|
|
76
|
+
receive_all_data = [byte for byte in receive_all_data]
|
|
77
|
+
return_data = ''
|
|
78
|
+
if flag == "voltage":
|
|
79
|
+
receive_data = self._extract_frame(receive_all_data, ProtocolCode.header, ProtocolCode.footer)
|
|
80
|
+
# print(receive_data, len(receive_data))
|
|
81
|
+
self._debug(receive_data)
|
|
82
|
+
transition_16 = 0
|
|
83
|
+
transition_16 |= receive_data[20] << 8
|
|
84
|
+
transition_16 |= receive_data[21]
|
|
85
|
+
return_data = round(transition_16 / 1000 + (transition_16 % 1000) * 0.001, 3)
|
|
86
|
+
|
|
87
|
+
return return_data
|
|
88
|
+
|
|
89
|
+
elif flag == "ultrasonic":
|
|
90
|
+
receive_data = self._extract_frame(receive_all_data, ProtocolCode.ultrasound_header,
|
|
91
|
+
ProtocolCode.ultrasound_footer)
|
|
92
|
+
# print(receive_data, len(receive_data))
|
|
93
|
+
self._debug(receive_data)
|
|
94
|
+
return_data = [receive_data[1] * 256 + receive_data[2], receive_data[3] * 256 + receive_data[4],
|
|
95
|
+
receive_data[5] * 256 + receive_data[6]]
|
|
96
|
+
return return_data
|
|
97
|
+
else:
|
|
98
|
+
print('no data', return_data)
|
|
99
|
+
|
|
100
|
+
def _extract_frame(self, data, frame_header, frame_tail):
|
|
101
|
+
"""
|
|
102
|
+
Extract the corresponding data
|
|
103
|
+
:param data: Get all data
|
|
104
|
+
:param frame_header: Frame Header
|
|
105
|
+
:param frame_tail: Frame tail
|
|
106
|
+
:return: A list of integers
|
|
107
|
+
"""
|
|
108
|
+
try:
|
|
109
|
+
# Find the location of the frame header
|
|
110
|
+
start_index = data.index(frame_header)
|
|
111
|
+
# Find the end of the frame, starting from the frame header
|
|
112
|
+
end_index = data.index(frame_tail, start_index)
|
|
113
|
+
# Extracting dataframe
|
|
114
|
+
frame = data[start_index:end_index + 1]
|
|
115
|
+
return frame
|
|
116
|
+
except ValueError:
|
|
117
|
+
# If the frame header or frame trailer is not found, an empty list is returned.
|
|
118
|
+
return []
|
|
119
|
+
|
|
120
|
+
def _check_sum(self, count_number, mode):
|
|
121
|
+
"""
|
|
122
|
+
Calculate the check digit
|
|
123
|
+
:param count_number: The total number of bytes before the check digit
|
|
124
|
+
:param mode: Verify whether to send or receive data, 0-Receive data mode, 1-Send data mode
|
|
125
|
+
:return: A byte type
|
|
126
|
+
"""
|
|
127
|
+
check_sum_result = 0
|
|
128
|
+
# 接收数据模式
|
|
129
|
+
if mode == 0:
|
|
130
|
+
for k in range(count_number):
|
|
131
|
+
check_sum_result ^= self.Send_Data[k]
|
|
132
|
+
# 发送数据模式
|
|
133
|
+
elif mode == 1:
|
|
134
|
+
for k in range(count_number):
|
|
135
|
+
check_sum_result ^= self.Send_Data[k]
|
|
136
|
+
|
|
137
|
+
return check_sum_result
|
|
138
|
+
|
|
139
|
+
def get_power_voltage(self):
|
|
140
|
+
"""
|
|
141
|
+
Get battery voltage
|
|
142
|
+
:return:
|
|
143
|
+
"""
|
|
144
|
+
return self._request("voltage")
|
|
145
|
+
|
|
146
|
+
def get_ultrasonic_value(self):
|
|
147
|
+
"""
|
|
148
|
+
Get ultrasonic value
|
|
149
|
+
:return:
|
|
150
|
+
"""
|
|
151
|
+
return self._request('ultrasonic')
|
|
152
|
+
|
|
153
|
+
def go_straight(self, speed=0.2):
|
|
154
|
+
"""
|
|
155
|
+
Forward control
|
|
156
|
+
:param speed: speed (float, optional): Movement speed. Defaults to 0.2. range 0 ~ 1
|
|
157
|
+
:return:
|
|
158
|
+
"""
|
|
159
|
+
if speed < 0 or speed > 1:
|
|
160
|
+
raise Exception("The movement speed range is 0~1, but the received value is {}".format(speed))
|
|
161
|
+
self.Send_Data[0] = ProtocolCode.header
|
|
162
|
+
self.Send_Data[1] = 0
|
|
163
|
+
self.Send_Data[2] = 0
|
|
164
|
+
# The target velocity of the X-axis of the robot
|
|
165
|
+
transition = int(speed * 1000)
|
|
166
|
+
self.Send_Data[4] = transition & 0xFF # Lower 8 bits
|
|
167
|
+
self.Send_Data[3] = (transition >> 8) & 0xFF # Higher 8 bits
|
|
168
|
+
# The target velocity of the Y-axis of the robot
|
|
169
|
+
self.Send_Data[6] = 0
|
|
170
|
+
self.Send_Data[5] = 0
|
|
171
|
+
|
|
172
|
+
self.Send_Data[8] = 0
|
|
173
|
+
self.Send_Data[7] = 0
|
|
174
|
+
# Check the bits for the Check_Sum function
|
|
175
|
+
self.Send_Data[9] = self._check_sum(9, 1)
|
|
176
|
+
self.Send_Data[10] = ProtocolCode.footer
|
|
177
|
+
|
|
178
|
+
try:
|
|
179
|
+
self._serial_port.write(bytes(self.Send_Data))
|
|
180
|
+
self._serial_port.flush()
|
|
181
|
+
self._debug(self.Send_Data)
|
|
182
|
+
except serial.SerialException as e:
|
|
183
|
+
e = traceback.format_exc()
|
|
184
|
+
print('Unable to send data through serial port: {}'.format(e))
|
|
185
|
+
|
|
186
|
+
def go_back(self, speed=-0.2):
|
|
187
|
+
"""
|
|
188
|
+
Back control
|
|
189
|
+
:param speed: speed (float, optional): Movement speed. Defaults to 0.25. range -1 ~ 0
|
|
190
|
+
:return:
|
|
191
|
+
"""
|
|
192
|
+
if not -1 <= speed <= 0:
|
|
193
|
+
raise Exception("The movement speed range is -1~0, but the received value is {}".format(speed))
|
|
194
|
+
self.Send_Data = [0] * 11
|
|
195
|
+
self.Send_Data[0] = ProtocolCode.header
|
|
196
|
+
self.Send_Data[1] = 0
|
|
197
|
+
self.Send_Data[2] = 0
|
|
198
|
+
# The target velocity of the X-axis of the robot
|
|
199
|
+
transition = int(speed * 1000)
|
|
200
|
+
if transition < 0:
|
|
201
|
+
transition = (1 << 16) + transition
|
|
202
|
+
self.Send_Data[4] = transition & 0xFF # Lower 8 bits
|
|
203
|
+
self.Send_Data[3] = (transition >> 8) & 0xFF # Higher 8 bits
|
|
204
|
+
# The target velocity of the Y-axis of the robot
|
|
205
|
+
self.Send_Data[6] = 0
|
|
206
|
+
self.Send_Data[5] = 0
|
|
207
|
+
# The target velocity of the Z-axis of the robot
|
|
208
|
+
self.Send_Data[8] = 0
|
|
209
|
+
self.Send_Data[7] = 0
|
|
210
|
+
# Check the bits for the Check_Sum function
|
|
211
|
+
self.Send_Data[9] = self._check_sum(9, 1)
|
|
212
|
+
self.Send_Data[10] = ProtocolCode.footer
|
|
213
|
+
|
|
214
|
+
try:
|
|
215
|
+
self._serial_port.write(bytes(self.Send_Data))
|
|
216
|
+
self._serial_port.flush()
|
|
217
|
+
self._debug(self.Send_Data)
|
|
218
|
+
except serial.SerialException as e:
|
|
219
|
+
e = traceback.format_exc()
|
|
220
|
+
print('Unable to send data through serial port: {}'.format(e))
|
|
221
|
+
|
|
222
|
+
def turn_left(self, speed=0.2):
|
|
223
|
+
"""
|
|
224
|
+
Left turn control
|
|
225
|
+
:param speed: speed (float, optional): Movement speed. Defaults to 0.2. range 0 ~ 1
|
|
226
|
+
:return:
|
|
227
|
+
"""
|
|
228
|
+
|
|
229
|
+
if speed < 0 or speed > 1:
|
|
230
|
+
raise Exception("The movement speed range is 0~1, but the received value is {}".format(speed))
|
|
231
|
+
self.Send_Data = [0] * 11
|
|
232
|
+
self.Send_Data[0] = ProtocolCode.header
|
|
233
|
+
self.Send_Data[1] = 0
|
|
234
|
+
self.Send_Data[2] = 0
|
|
235
|
+
# The target velocity of the X-axis of the robot
|
|
236
|
+
self.Send_Data[4] = 0
|
|
237
|
+
self.Send_Data[3] = 0
|
|
238
|
+
# The target velocity of the Y-axis of the robot
|
|
239
|
+
self.Send_Data[6] = 0
|
|
240
|
+
self.Send_Data[5] = 0
|
|
241
|
+
# The target velocity of the Z-axis of the robot
|
|
242
|
+
transition = int(speed * 1000)
|
|
243
|
+
self.Send_Data[8] = transition & 0xFF # Lower 8 bits
|
|
244
|
+
self.Send_Data[7] = (transition >> 8) & 0xFF # Higher 8 bits
|
|
245
|
+
# Check the bits for the Check_Sum function
|
|
246
|
+
self.Send_Data[9] = self._check_sum(9, 1)
|
|
247
|
+
self.Send_Data[10] = ProtocolCode.footer
|
|
248
|
+
|
|
249
|
+
try:
|
|
250
|
+
self._serial_port.write(bytes(self.Send_Data))
|
|
251
|
+
self._serial_port.flush()
|
|
252
|
+
self._debug(self.Send_Data)
|
|
253
|
+
except serial.SerialException as e:
|
|
254
|
+
e = traceback.format_exc()
|
|
255
|
+
print('Unable to send data through serial port: {}'.format(e))
|
|
256
|
+
|
|
257
|
+
def turn_right(self, speed=-0.2):
|
|
258
|
+
"""
|
|
259
|
+
Right turn control
|
|
260
|
+
:param speed: speed (float, optional): Movement speed. Defaults to -0.2. range -1 ~ 0
|
|
261
|
+
:return:
|
|
262
|
+
"""
|
|
263
|
+
if not -1 <= speed <= 0:
|
|
264
|
+
raise Exception("The movement speed range is -1~0, but the received value is {}".format(speed))
|
|
265
|
+
self.Send_Data = [0] * 11
|
|
266
|
+
|
|
267
|
+
self.Send_Data[0] = ProtocolCode.header
|
|
268
|
+
self.Send_Data[1] = 0
|
|
269
|
+
self.Send_Data[2] = 0
|
|
270
|
+
# The target velocity of the X-axis of the robot
|
|
271
|
+
self.Send_Data[4] = 0
|
|
272
|
+
self.Send_Data[3] = 0
|
|
273
|
+
# The target velocity of the Y-axis of the robot
|
|
274
|
+
self.Send_Data[6] = 0
|
|
275
|
+
self.Send_Data[5] = 0
|
|
276
|
+
# The target velocity of the Z-axis of the robot
|
|
277
|
+
transition = int(speed * 1000)
|
|
278
|
+
if transition < 0:
|
|
279
|
+
transition = (1 << 16) + transition
|
|
280
|
+
self.Send_Data[8] = transition & 0xFF # Lower 8 bits
|
|
281
|
+
self.Send_Data[7] = (transition >> 8) & 0xFF # Higher 8 bits
|
|
282
|
+
# Check the bits for the Check_Sum function
|
|
283
|
+
self.Send_Data[9] = self._check_sum(9, 1)
|
|
284
|
+
self.Send_Data[10] = ProtocolCode.footer
|
|
285
|
+
|
|
286
|
+
try:
|
|
287
|
+
self._serial_port.write(bytes(self.Send_Data))
|
|
288
|
+
self._serial_port.flush()
|
|
289
|
+
self._debug(self.Send_Data)
|
|
290
|
+
except serial.SerialException as e:
|
|
291
|
+
e = traceback.format_exc()
|
|
292
|
+
print('Unable to send data through serial port: {}'.format(e))
|
|
293
|
+
|
|
294
|
+
def stop(self):
|
|
295
|
+
"""
|
|
296
|
+
stop motion
|
|
297
|
+
:return:
|
|
298
|
+
"""
|
|
299
|
+
self.Send_Data = [0] * 11
|
|
300
|
+
self.Send_Data[0] = ProtocolCode.header
|
|
301
|
+
self.Send_Data[1] = 0
|
|
302
|
+
self.Send_Data[2] = 0
|
|
303
|
+
# The target velocity of the X-axis of the robot
|
|
304
|
+
self.Send_Data[4] = 0
|
|
305
|
+
self.Send_Data[3] = 0
|
|
306
|
+
# The target velocity of the Y-axis of the robot
|
|
307
|
+
self.Send_Data[6] = 0
|
|
308
|
+
self.Send_Data[5] = 0
|
|
309
|
+
# The target velocity of the Z-axis of the robot
|
|
310
|
+
self.Send_Data[8] = 0
|
|
311
|
+
self.Send_Data[7] = 0
|
|
312
|
+
# Check the bits for the Check_Sum function
|
|
313
|
+
self.Send_Data[9] = self._check_sum(9, 1)
|
|
314
|
+
self.Send_Data[10] = ProtocolCode.footer
|
|
315
|
+
|
|
316
|
+
try:
|
|
317
|
+
self._serial_port.write(bytes(self.Send_Data))
|
|
318
|
+
self._serial_port.flush()
|
|
319
|
+
self._debug(self.Send_Data)
|
|
320
|
+
except serial.SerialException as e:
|
|
321
|
+
e = traceback.format_exc()
|
|
322
|
+
print('Unable to send data through serial port: {}'.format(e))
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
# mc = ChassisControl('/dev/wheeltec_controller', debug=True)
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import socket
|
|
3
|
-
import json
|
|
4
|
-
import threading
|
|
5
|
-
import struct
|
|
6
|
-
|
|
7
|
-
class MercuryChassisError(Exception):
|
|
8
|
-
pass
|
|
9
|
-
|
|
10
|
-
class MercuryChassis:
|
|
11
|
-
"""
|
|
12
|
-
Mercury X1 mobile chassis car socket class
|
|
13
|
-
"""
|
|
14
|
-
def __init__(self, ip=None):
|
|
15
|
-
self.ifname = b"wlan0"
|
|
16
|
-
self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
17
|
-
if ip is not None:
|
|
18
|
-
self.host = ip
|
|
19
|
-
else:
|
|
20
|
-
import fcntl
|
|
21
|
-
try:
|
|
22
|
-
self.host = socket.inet_ntoa(fcntl.ioctl(self.server_socket.fileno(), 0x8915, struct.pack('256s', self.ifname[:15]))[20:24]) #IP
|
|
23
|
-
except:
|
|
24
|
-
self.host = "127.0.0.1"
|
|
25
|
-
self._sock.connect((self.host, 9999))
|
|
26
|
-
self.recv = threading.Thread(target=self.check_move_end, daemon=True)
|
|
27
|
-
self.recv.start()
|
|
28
|
-
self.move_end = False
|
|
29
|
-
|
|
30
|
-
def close(self):
|
|
31
|
-
self._sock.close()
|
|
32
|
-
|
|
33
|
-
def open(self):
|
|
34
|
-
self._sock.connect((self.host, 9999))
|
|
35
|
-
|
|
36
|
-
def check_move_end(self):
|
|
37
|
-
while True:
|
|
38
|
-
try:
|
|
39
|
-
data = self._sock.recv(1024)
|
|
40
|
-
data = json.loads(data)
|
|
41
|
-
self.move_end = data
|
|
42
|
-
except:
|
|
43
|
-
pass
|
|
44
|
-
|
|
45
|
-
# @property
|
|
46
|
-
def is_move_end(self):
|
|
47
|
-
"""Is the movement over
|
|
48
|
-
|
|
49
|
-
Returns:
|
|
50
|
-
_type_: _description_
|
|
51
|
-
"""
|
|
52
|
-
return self.move_end
|
|
53
|
-
|
|
54
|
-
def go_straight(self, speed=0.25, exercise_duration=5):
|
|
55
|
-
"""Forward control
|
|
56
|
-
|
|
57
|
-
Args:
|
|
58
|
-
speed (float, optional): Movement speed. Defaults to 0.25. range 0 ~ 1
|
|
59
|
-
exercise_duration (int, optional): Exercise duration. Defaults to 5s.
|
|
60
|
-
"""
|
|
61
|
-
if speed < 0 or speed > 1:
|
|
62
|
-
raise MercuryChassisError("The movement speed range is 0~1, but the received value is {}".format(speed))
|
|
63
|
-
command = {"goStraight": {"time": exercise_duration, "speed": speed}}
|
|
64
|
-
self._sock.sendall(json.dumps(command).encode())
|
|
65
|
-
|
|
66
|
-
def go_back(self, speed=0.25, exercise_duration=5):
|
|
67
|
-
"""Back control
|
|
68
|
-
|
|
69
|
-
Args:
|
|
70
|
-
speed (float, optional): Movement speed. Defaults to 0.25. range 0 ~ 1
|
|
71
|
-
exercise_duration (int, optional): Exercise duration. Defaults to 5s.
|
|
72
|
-
"""
|
|
73
|
-
if speed < 0 or speed > 1:
|
|
74
|
-
raise MercuryChassisError("The movement speed range is 0~1, but the received value is {}".format(speed))
|
|
75
|
-
command = {"goBack": {"time": exercise_duration, "speed": speed}}
|
|
76
|
-
self._sock.sendall(json.dumps(command).encode())
|
|
77
|
-
|
|
78
|
-
def turn_left(self, speed=0.5, exercise_duration=5):
|
|
79
|
-
"""left turn control
|
|
80
|
-
|
|
81
|
-
Args:
|
|
82
|
-
speed (float, optional): Movement speed. Defaults to 0.25. range 0 ~ 1
|
|
83
|
-
exercise_duration (int, optional): Exercise duration. Defaults to 5s.
|
|
84
|
-
"""
|
|
85
|
-
if speed < 0 or speed > 1:
|
|
86
|
-
raise MercuryChassisError("The movement speed range is 0~1, but the received value is {}".format(speed))
|
|
87
|
-
command = {"turnLeft": {"time": exercise_duration, "speed": speed}}
|
|
88
|
-
self._sock.sendall(json.dumps(command).encode())
|
|
89
|
-
|
|
90
|
-
def turn_right(self, speed=0.5, exercise_duration=5):
|
|
91
|
-
"""_summary_
|
|
92
|
-
|
|
93
|
-
Args:
|
|
94
|
-
speed (float, optional): Movement speed. Defaults to 0.25. range 0 ~ 1
|
|
95
|
-
exercise_duration (int, optional): Exercise duration. Defaults to 5s.
|
|
96
|
-
"""
|
|
97
|
-
if speed < 0 or speed > 1:
|
|
98
|
-
raise MercuryChassisError("The movement speed range is 0~1, but the received value is {}".format(speed))
|
|
99
|
-
command = {"turnRight": {"time": exercise_duration, "speed": speed}}
|
|
100
|
-
self._sock.sendall(json.dumps(command).encode())
|
|
101
|
-
|
|
102
|
-
def stop(self):
|
|
103
|
-
"""stop motion"""
|
|
104
|
-
command = {"stop": True}
|
|
105
|
-
self._sock.sendall(json.dumps(command).encode())
|
|
106
|
-
|
|
107
|
-
def init_position(self,position_x,position_y,orientation_z,orientation_w,covariance):
|
|
108
|
-
"""Set navigation starting position
|
|
109
|
-
|
|
110
|
-
Args:
|
|
111
|
-
position_x (_type_): _description_
|
|
112
|
-
position_y (_type_): _description_
|
|
113
|
-
orientation_z (_type_): _description_
|
|
114
|
-
orientation_w (_type_): _description_
|
|
115
|
-
covariance (_type_): _description_
|
|
116
|
-
"""
|
|
117
|
-
command = {"initPosition": {"x": position_x, "y": position_y, "o_z": orientation_z, "o_w": orientation_w, "cov": covariance}}
|
|
118
|
-
self._sock.sendall(json.dumps(command).encode())
|
|
119
|
-
|
|
120
|
-
def goto_position(self,position_x,position_y,orientation_z,orientation_w):
|
|
121
|
-
"""Set navigation target location
|
|
122
|
-
|
|
123
|
-
Args:
|
|
124
|
-
position_x (_type_): _description_
|
|
125
|
-
position_y (_type_): _description_
|
|
126
|
-
orientation_z (_type_): _description_
|
|
127
|
-
orientation_w (_type_): _description_
|
|
128
|
-
"""
|
|
129
|
-
command = {"goToPosition": {"x": position_x, "y": position_y, "o_z": orientation_z, "o_w": orientation_w}}
|
|
130
|
-
self._sock.sendall(json.dumps(command).encode())
|
|
131
|
-
|
|
132
|
-
def cancel_navigation(self):
|
|
133
|
-
"""Cancel navigation
|
|
134
|
-
"""
|
|
135
|
-
command = {"movebaseCancel": True}
|
|
136
|
-
self._sock.sendall(json.dumps(command).encode())
|
|
137
|
-
|
|
138
|
-
def get_software_version(self):
|
|
139
|
-
"""Get the base server version number"""
|
|
140
|
-
command = {"getSoftWareVersion": True}
|
|
141
|
-
self._sock.sendall(json.dumps(command).encode())
|
|
142
|
-
while True:
|
|
143
|
-
if self.move_end:
|
|
144
|
-
data = self.move_end.get("getSoftWareVersion", None)
|
|
145
|
-
if data:
|
|
146
|
-
return self.move_end["getSoftWareVersion"]["return"]
|
|
147
|
-
|
|
148
|
-
def get_base_ros_version(self):
|
|
149
|
-
"""Get the base ROS project version number"""
|
|
150
|
-
command = {"getBaseROSVersion": True}
|
|
151
|
-
self._sock.sendall(json.dumps(command).encode())
|
|
152
|
-
while True:
|
|
153
|
-
if self.move_end:
|
|
154
|
-
data = self.move_end.get("getBaseROSVersion", None)
|
|
155
|
-
if data:
|
|
156
|
-
return self.move_end["getBaseROSVersion"]["return"]
|
|
157
|
-
|
|
158
|
-
def get_battery_state(self):
|
|
159
|
-
"""Get battery level
|
|
160
|
-
"""
|
|
161
|
-
command = {"batteryState": True}
|
|
162
|
-
self._sock.sendall(json.dumps(command).encode())
|
|
163
|
-
while True:
|
|
164
|
-
if self.move_end:
|
|
165
|
-
data = self.move_end.get("batteryState", None)
|
|
166
|
-
if data:
|
|
167
|
-
return self.move_end["batteryState"]["return"]
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|