zyworkflow 0.0.1__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.
File without changes
@@ -0,0 +1,50 @@
1
+ import os
2
+ import sys
3
+ from loguru import logger
4
+
5
+
6
+ def setup_logger(
7
+ name: str,
8
+ log_dir: str = "./logs",
9
+ level: str = "INFO",
10
+ retention: str = "7 days",
11
+ rotation: str = "00:00"
12
+ ):
13
+ os.makedirs(log_dir, exist_ok=True)
14
+
15
+ logger.remove()
16
+ logger.add(
17
+ sys.stderr,
18
+ format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
19
+ level=level,
20
+ colorize=True
21
+ )
22
+
23
+ log_file = os.path.join(log_dir, f"{name}_{{time:YYYY-MM-DD}}.log")
24
+ logger.add(
25
+ log_file,
26
+ rotation=rotation,
27
+ retention=retention,
28
+ format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} - {message}",
29
+ level="DEBUG",
30
+ encoding="utf-8",
31
+ enqueue=True
32
+ )
33
+
34
+ return logger
35
+
36
+
37
+ def setup_api_server_logger():
38
+ return setup_logger("api_server", log_dir="/workspace/logs/api_server")
39
+
40
+
41
+ def setup_train_client_logger():
42
+ return setup_logger("train_client", log_dir="/workspace/logs/train_client")
43
+
44
+
45
+ def setup_data_collection_logger():
46
+ return setup_logger("data_collection", log_dir="/workspace/logs/data_collection")
47
+
48
+
49
+ def setup_train_pick_policy_logger():
50
+ return setup_logger("train_pick_policy", log_dir="/workspace/logs/train_pick_policy")
@@ -0,0 +1,131 @@
1
+ import numpy as np
2
+ from typing import Sequence
3
+
4
+
5
+ def get_gripper_pose(end_in_base_pose6: Sequence[float],) -> np.ndarray:
6
+ T_end_tool = np.array([
7
+ [1.0, 0.0, 0.0, 0.0 ],
8
+ [0.0, 1.0, 0.0, 0.0 ],
9
+ [0.0, 0.0, 1.0, 0.17],
10
+ [0.0, 0.0, 0.0, 1.0 ],
11
+ ], dtype=float)
12
+
13
+ def Rx(a: float) -> np.ndarray:
14
+ c, s = np.cos(a), np.sin(a)
15
+ return np.array([[1,0,0],[0,c,-s],[0,s,c]], dtype=float)
16
+
17
+ def Ry(a: float) -> np.ndarray:
18
+ c, s = np.cos(a), np.sin(a)
19
+ return np.array([[c,0,s],[0,1,0],[-s,0,c]], dtype=float)
20
+
21
+ def Rz(a: float) -> np.ndarray:
22
+ c, s = np.cos(a), np.sin(a)
23
+ return np.array([[c,-s,0],[s,c,0],[0,0,1]], dtype=float)
24
+
25
+ def euler_zyx_to_R(rx: float, ry: float, rz: float) -> np.ndarray:
26
+ return Rz(rz) @ Ry(ry) @ Rx(rx)
27
+
28
+ def make_T(R: np.ndarray, t: Sequence[float]) -> np.ndarray:
29
+ T = np.eye(4, dtype=float)
30
+ T[:3, :3] = np.asarray(R, dtype=float).reshape(3, 3)
31
+ T[:3, 3] = np.asarray(t, dtype=float).reshape(3)
32
+ return T
33
+
34
+ def R_to_euler_zyx(R: np.ndarray) -> tuple[float, float, float]:
35
+ R = np.asarray(R, dtype=float).reshape(3, 3)
36
+
37
+ sy = float(np.clip(-R[2, 0], -1.0, 1.0))
38
+ ry = float(np.arcsin(sy))
39
+ cy = float(np.cos(ry))
40
+
41
+ if abs(cy) > 1e-8:
42
+ rx = float(np.arctan2(R[2, 1], R[2, 2]))
43
+ rz = float(np.arctan2(R[1, 0], R[0, 0]))
44
+ else:
45
+ rz = 0.0
46
+ rx = float(np.arctan2(-R[0, 1], R[1, 1]))
47
+
48
+ return rx, ry, rz
49
+
50
+ end6 = np.asarray(end_in_base_pose6, dtype=float).reshape(6)
51
+ x, y, z, rx, ry, rz = end6.tolist()
52
+
53
+ T_base_end = make_T(euler_zyx_to_R(rx, ry, rz), [x, y, z])
54
+ T_base_tool = T_base_end @ T_end_tool
55
+
56
+ t_bt = T_base_tool[:3, 3]
57
+ rx_t, ry_t, rz_t = R_to_euler_zyx(T_base_tool[:3, :3])
58
+ return np.array([t_bt[0], t_bt[1], t_bt[2], rx_t, ry_t, rz_t], dtype=float)
59
+
60
+
61
+ def get_target_pose(end_in_base_pose6: Sequence[float], obj_in_cam_pose7: Sequence[float],) -> np.ndarray:
62
+ # TODO: 需要根据实际情况调整, 未来要传参数进来
63
+ T_EE_CAM = np.array([
64
+ [-0.9801513, -0.12894636, -0.15058639, 0.04160245],
65
+ [ 0.19782898, -0.68568308, -0.70050154, 0.15992103],
66
+ [ -0.01292742, -0.71638785, 0.69758249, 0.11156246],
67
+ [ 0.0, 0.0, 0.0, 1.0 ],
68
+ ], dtype=float)
69
+
70
+ def Rx(a):
71
+ c, s = np.cos(a), np.sin(a)
72
+ return np.array([[1,0,0],[0,c,-s],[0,s,c]], dtype=float)
73
+
74
+ def Ry(a):
75
+ c, s = np.cos(a), np.sin(a)
76
+ return np.array([[c,0,s],[0,1,0],[-s,0,c]], dtype=float)
77
+
78
+ def Rz(a):
79
+ c, s = np.cos(a), np.sin(a)
80
+ return np.array([[c,-s,0],[s,c,0],[0,0,1]], dtype=float)
81
+
82
+ def euler_zyx_to_R(rx, ry, rz):
83
+ return Rz(rz) @ Ry(ry) @ Rx(rx)
84
+
85
+ def quat_xyzw_to_R(q):
86
+ q = np.asarray(q, dtype=float).reshape(4)
87
+ q = q / (np.linalg.norm(q) + 1e-12)
88
+ x, y, z, w = q
89
+ return np.array([
90
+ [1 - 2*(y*y + z*z), 2*(x*y - z*w), 2*(x*z + y*w)],
91
+ [ 2*(x*y + z*w), 1 - 2*(x*x + z*z), 2*(y*z - x*w)],
92
+ [ 2*(x*z - y*w), 2*(y*z + x*w), 1 - 2*(x*x + y*y)],
93
+ ], dtype=float)
94
+
95
+ def R_to_euler_zyx(R):
96
+ R = np.asarray(R, dtype=float).reshape(3, 3)
97
+
98
+ sy = float(np.clip(-R[2, 0], -1.0, 1.0))
99
+ ry = float(np.arcsin(sy))
100
+ cy = float(np.cos(ry))
101
+
102
+ if abs(cy) > 1e-8:
103
+ rx = float(np.arctan2(R[2, 1], R[2, 2]))
104
+ rz = float(np.arctan2(R[1, 0], R[0, 0]))
105
+ else:
106
+ rz = 0.0
107
+ rx = float(np.arctan2(-R[0, 1], R[1, 1]))
108
+
109
+ return rx, ry, rz
110
+
111
+ def make_T(R, t):
112
+ T = np.eye(4, dtype=float)
113
+ T[:3, :3] = np.asarray(R, dtype=float).reshape(3, 3)
114
+ T[:3, 3] = np.asarray(t, dtype=float).reshape(3)
115
+ return T
116
+
117
+ end6 = np.asarray(end_in_base_pose6, dtype=float).reshape(6)
118
+ ex, ey, ez, erx, ery, erz = end6.tolist()
119
+ T_base_ee = make_T(euler_zyx_to_R(erx, ery, erz), [ex, ey, ez])
120
+
121
+ obj7 = np.asarray(obj_in_cam_pose7, dtype=float).reshape(7)
122
+ t_co = obj7[:3]
123
+ q_co = obj7[3:]
124
+ T_cam_obj = make_T(quat_xyzw_to_R(q_co), t_co)
125
+
126
+ T_base_obj = T_base_ee @ T_EE_CAM @ T_cam_obj
127
+
128
+ t_bo = T_base_obj[:3, 3]
129
+ rx, ry, rz = R_to_euler_zyx(T_base_obj[:3, :3])
130
+
131
+ return np.array([t_bo[0], t_bo[1], t_bo[2], rx, ry, rz], dtype=float)
@@ -0,0 +1,264 @@
1
+ # coding: utf-8
2
+ import io
3
+ import cv2
4
+ import requests
5
+ import collections
6
+ import numpy as np
7
+ from PIL import Image
8
+ from zyworkflow.utils.logger_config import setup_api_server_logger
9
+ logger = setup_api_server_logger()
10
+
11
+
12
+ try:
13
+ collectionsAbc = collections.abc
14
+ except AttributeError:
15
+ collectionsAbc = collections
16
+ callback_url = "http://192.168.1.103:8888/api/v1/task/end"
17
+ rgb_image_url = "http://192.168.1.102:8660/api/robot/rgb_image?dev=top_camera"
18
+ depth_image_url = "http://192.168.1.102:8660/api/robot/depth_image?dev=top_camera"
19
+ arm_status = "http://192.168.1.102:8660/api/arm/pose"
20
+ arm_movej = "http://192.168.1.102:8660/api/arm/move-j"
21
+ arm_movel = "http://192.168.1.102:8660/api/arm/move-l"
22
+ arm_stop = "http://192.168.1.102:8660/api/arm/stop"
23
+ gripper_move = "http://192.168.1.102:8660/api/arm/gripper-position"
24
+ gripper_status = "http://192.168.1.102:8660/api/gripper/status"
25
+ dof = "http://192.168.112.161:58896/api/call-service/calculate"
26
+ find_basket = "http://192.168.112.161:58896/api/call-service/find_basket"
27
+
28
+
29
+ class AttrDict(dict):
30
+ def __init__(self, **kwargs):
31
+ super(AttrDict, self).__init__()
32
+ super(AttrDict, self).update(kwargs)
33
+
34
+ def __getattr__(self, key):
35
+ if key in self:
36
+ return self[key]
37
+ raise AttributeError("没有找到key:'{}'".format(key))
38
+
39
+
40
+ global_config = AttrDict()
41
+
42
+
43
+ def preprocess_image(img):
44
+ img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
45
+ img = img.transpose(2, 0, 1)
46
+ img = img.astype(np.float32) / 255.0
47
+ return img
48
+
49
+
50
+ def register(name=None):
51
+ if callable(name):
52
+ cls = name
53
+ return register()(cls)
54
+
55
+ def wrapper(cls):
56
+ nonlocal name
57
+ if isinstance(cls, type) and cls.__name__ in global_config:
58
+ raise ValueError(f"该类{cls.__name__}已经被注册过")
59
+ if not isinstance(cls, type) and callable(cls):
60
+ func = cls
61
+ cls = type(
62
+ cls.__name__, (object,), {
63
+ '__call__': lambda _, *arg, **kws: func(*arg, **kws),
64
+ '__doc__': func.__doc__,
65
+ })
66
+ if name:
67
+ global_config[name] = cls
68
+ else:
69
+ global_config[cls.__name__] = cls
70
+
71
+ return cls
72
+
73
+ return wrapper
74
+
75
+
76
+ def create(cls_or_name, args=None, kws=None):
77
+ assert type(cls_or_name) in [type, str], "必须是类或类的名字"
78
+ name = type(cls_or_name) == str and cls_or_name or cls_or_name.__name__
79
+ cls = global_config[name]
80
+ if args is None:
81
+ args = ()
82
+ if kws is None:
83
+ kws = {}
84
+
85
+ return cls(*args, **kws)
86
+
87
+
88
+ def get_image(url):
89
+ try:
90
+ response = requests.get(url, timeout=10)
91
+ response.raise_for_status()
92
+ jpg_bytes = response.content
93
+
94
+ image_stream = io.BytesIO(jpg_bytes)
95
+ image = Image.open(image_stream)
96
+ image_array = np.array(image)
97
+
98
+ return image_array, ""
99
+
100
+ except requests.exceptions.RequestException as e:
101
+ logger.error(f"获取URL图片失败:{str(e)}")
102
+ return None, f"获取URL图片失败:{str(e)}"
103
+ except Exception as e:
104
+ logger.error(f"转换为numpy数组失败:{str(e)}")
105
+ return None, f"转换为numpy数组失败:{str(e)}"
106
+
107
+
108
+ def get_arm_status():
109
+ try:
110
+ response = requests.get(arm_status, timeout=10)
111
+ response.raise_for_status()
112
+ result = response.json()
113
+
114
+ status = result.get('status')
115
+ return status, ""
116
+
117
+ except requests.exceptions.RequestException as e:
118
+ logger.error(f"获取URL机械臂状态失败:{str(e)}")
119
+ return None, f"获取URL机械臂状态失败:{str(e)}"
120
+ except Exception as e:
121
+ logger.error(f"读取机械臂状态失败:{str(e)}")
122
+ return None, f"读取机械臂状态失败:{str(e)}"
123
+
124
+
125
+ def get_gripper_status():
126
+ try:
127
+ response = requests.get(gripper_status, timeout=10)
128
+ response.raise_for_status()
129
+ result = response.json()
130
+
131
+ grip_state = result.get('grip_state')
132
+ position = result.get('position')
133
+ set_position = result.get('set_position')
134
+ return grip_state, set_position, position, ""
135
+
136
+ except requests.exceptions.RequestException as e:
137
+ logger.error(f"获取URL夹爪状态失败:{str(e)}")
138
+ return None, None, None, f"获取URL夹爪状态失败:{str(e)}"
139
+ except Exception as e:
140
+ logger.error(f"读取机械臂夹爪失败:{str(e)}")
141
+ return None, None, None, f"读取机械臂夹爪失败:{str(e)}"
142
+
143
+
144
+ def post_arm_movej(joints, speed=10):
145
+ try:
146
+ data = {'joints': [float(joint) for joint in joints], "speed": speed}
147
+ response = requests.post(arm_movej, json=data, timeout=100)
148
+ response.raise_for_status()
149
+ result = response.json()
150
+
151
+ code = result['code']
152
+ return code, ""
153
+
154
+ except requests.exceptions.RequestException as e:
155
+ logger.error(f"获取URL机械臂movej失败:{str(e)}")
156
+ return None, f"获取URL机械臂movej失败:{str(e)}"
157
+ except Exception as e:
158
+ logger.error(f"解析movej返回值失败:{str(e)}")
159
+ return None, f"解析movej返回值失败:{str(e)}"
160
+
161
+
162
+ def post_arm_movel(poses, speed=10):
163
+ try:
164
+ data = {'pose': [float(pose) for pose in poses], "speed": speed}
165
+ response = requests.post(arm_movel, json=data, timeout=100)
166
+ response.raise_for_status()
167
+ result = response.json()
168
+
169
+ code = result['code']
170
+ return code, ""
171
+
172
+ except requests.exceptions.RequestException as e:
173
+ logger.error(f"获取URL机械臂movel失败:{str(e)}")
174
+ return None, f"获取URL机械臂movel失败:{str(e)}"
175
+ except Exception as e:
176
+ logger.error(f"解析movel返回值失败:{str(e)}")
177
+ return None, f"解析movel返回值失败:{str(e)}"
178
+
179
+
180
+ def post_gripper_move(pos):
181
+ try:
182
+ data = {'pos': int(pos)}
183
+ response = requests.post(gripper_move, json=data, timeout=100)
184
+ response.raise_for_status()
185
+ result = response.text
186
+
187
+ return result, ""
188
+
189
+ except requests.exceptions.RequestException as e:
190
+ logger.error(f"获取URL夹爪move失败:{str(e)}")
191
+ return None, f"获取URL夹爪move失败:{str(e)}"
192
+ except Exception as e:
193
+ logger.error(f"解析夹爪move返回值失败:{str(e)}")
194
+ return None, f"解析夹爪move返回值失败:{str(e)}"
195
+
196
+
197
+ def post_6dof(sku):
198
+ try:
199
+ data = {'class_id': sku}
200
+ response = requests.post(dof, json=data, timeout=100)
201
+ response.raise_for_status()
202
+ result = response.json()
203
+
204
+ status = result['data']['ok']
205
+ try:
206
+ xyz = result['data']['xyz']
207
+ quat_xyzw = result['data']['quat_xyzw']
208
+ logger.info(f"xyz:{xyz}, quat_xyz: {quat_xyzw}")
209
+ except Exception as e:
210
+ logger.error(f"JSON解析失败: {e}")
211
+ return None, None, ""
212
+
213
+ return xyz, quat_xyzw, ""
214
+
215
+ except requests.exceptions.RequestException as e:
216
+ logger.error(f"获取URL 6dof失败:{str(e)}")
217
+ return None, None, f"获取URL 6dof失败:{str(e)}"
218
+ except Exception as e:
219
+ logger.error(f"解析6dof返回值失败:{str(e)}")
220
+ return None, None, f"解析6dof返回值失败:{str(e)}"
221
+
222
+
223
+ def post_find_basket():
224
+ try:
225
+ data = {}
226
+ response = requests.post(find_basket, json=data, timeout=100)
227
+ response.raise_for_status()
228
+ result = response.json()
229
+
230
+ status = result['data']['ok']
231
+ try:
232
+ xyz = result['data']['xyz']
233
+ quat_xyzw = result['data']['quat_xyzw']
234
+ logger.info(f"xyz:{xyz}, quat_xyz: {quat_xyzw}")
235
+ except Exception as e:
236
+ logger.error(f"JSON解析失败: {e}")
237
+ return None, None, ""
238
+
239
+ return xyz, quat_xyzw, ""
240
+
241
+ except requests.exceptions.RequestException as e:
242
+ logger.error(f"获取URL 6dof失败:{str(e)}")
243
+ return None, None, f"获取URL 6dof失败:{str(e)}"
244
+ except Exception as e:
245
+ logger.error(f"解析6dof返回值失败:{str(e)}")
246
+ return None, None, f"解析6dof返回值失败:{str(e)}"
247
+
248
+
249
+ def post_arm_stop():
250
+ try:
251
+ data = {}
252
+ response = requests.post(arm_stop, json=data, timeout=100)
253
+ response.raise_for_status()
254
+ result = response.json()
255
+
256
+ code = result['code']
257
+ return code, ""
258
+
259
+ except requests.exceptions.RequestException as e:
260
+ logger.error(f"获取URL机械臂stop失败:{str(e)}")
261
+ return None, f"获取URL机械臂stop失败:{str(e)}"
262
+ except Exception as e:
263
+ logger.error(f"解析stop返回值失败:{str(e)}")
264
+ return None, f"解析stop返回值失败:{str(e)}"
@@ -0,0 +1,11 @@
1
+ Metadata-Version: 2.4
2
+ Name: zyworkflow
3
+ Version: 0.0.1
4
+ Summary: Need Python3.9+
5
+ License: Apache License 2.0
6
+ Requires-Dist: psutil
7
+ Requires-Dist: Cython
8
+ Requires-Dist: aiohttp
9
+ Dynamic: license
10
+ Dynamic: requires-dist
11
+ Dynamic: summary
@@ -0,0 +1,19 @@
1
+ zyworkflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ zyworkflow/api_server.py,sha256=hcLuwI2vmquHkgQ6EzTwfD_iERMANSramL7hP_pSIWc,26684
3
+ zyworkflow/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ zyworkflow/data/collection.py,sha256=3aj8n7w31muccCfRdin5DzEbNZaTMC4hmWlWc6T5wUk,48507
5
+ zyworkflow/data/process.py,sha256=eK1nrtPOIlOA_x6dTjIIMiQEfvIiY7UpELkiGHDgtBw,2626
6
+ zyworkflow/doc/api.md,sha256=rqV9eDsHMRyTbg3T6QhLdG4j9R_bMfDGehMt2APkNNw,12061
7
+ zyworkflow/example/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ zyworkflow/example/train_client.py,sha256=JMdYX-FwNcGOU8u6ykyqlvkXF4KCUkd8iOK9ABNVzxQ,13317
9
+ zyworkflow/example/train_client_example.py,sha256=Y2W4rUsppoyVeovqE3yH1OkQ81mkqizTuTk9YKVY5w8,965
10
+ zyworkflow/policy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ zyworkflow/policy/train_pick_policy.py,sha256=-QjM9CMokQ4_uI8Y4Va-9BefelvCgxCPQ3-HeLD6tRk,31929
12
+ zyworkflow/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ zyworkflow/utils/logger_config.py,sha256=oaEd204gMoj9591CtQFEITStJzSPr2PzF015rEgJDX4,1372
14
+ zyworkflow/utils/pose.py,sha256=JXjmxVCvlq0jXTFykGJDiHlzehkursZMBY-99UipM6U,4417
15
+ zyworkflow/utils/utils.py,sha256=yRLzUwWP1sPbfRoghnm2kgTvo0tBOHW1wRuF1NXstN8,8709
16
+ zyworkflow-0.0.1.dist-info/METADATA,sha256=TfNviS3rH2G62rzAVvQje0SHyp9n2ATTgNt-EhV-cJ0,231
17
+ zyworkflow-0.0.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
18
+ zyworkflow-0.0.1.dist-info/top_level.txt,sha256=Hc13aPsoEw0Zc0BhJjR2vl8AvTqsyemSK_mYUJRttUk,11
19
+ zyworkflow-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ zyworkflow