hex-zmq-servers 0.3.9__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.
- hex_zmq_servers/__init__.py +173 -0
- hex_zmq_servers/cam/__init__.py +52 -0
- hex_zmq_servers/cam/berxel/__init__.py +17 -0
- hex_zmq_servers/cam/berxel/cam_berxel.py +282 -0
- hex_zmq_servers/cam/berxel/cam_berxel_cli.py +33 -0
- hex_zmq_servers/cam/berxel/cam_berxel_srv.py +79 -0
- hex_zmq_servers/cam/cam_base.py +189 -0
- hex_zmq_servers/cam/dummy/__init__.py +17 -0
- hex_zmq_servers/cam/dummy/cam_dummy.py +69 -0
- hex_zmq_servers/cam/dummy/cam_dummy_cli.py +29 -0
- hex_zmq_servers/cam/dummy/cam_dummy_srv.py +68 -0
- hex_zmq_servers/cam/realsense/__init__.py +17 -0
- hex_zmq_servers/cam/realsense/cam_realsense.py +159 -0
- hex_zmq_servers/cam/realsense/cam_realsense_cli.py +33 -0
- hex_zmq_servers/cam/realsense/cam_realsense_srv.py +78 -0
- hex_zmq_servers/cam/rgb/__init__.py +17 -0
- hex_zmq_servers/cam/rgb/cam_rgb.py +135 -0
- hex_zmq_servers/cam/rgb/cam_rgb_cli.py +43 -0
- hex_zmq_servers/cam/rgb/cam_rgb_srv.py +78 -0
- hex_zmq_servers/config/cam_berxel.json +18 -0
- hex_zmq_servers/config/cam_dummy.json +12 -0
- hex_zmq_servers/config/cam_realsense.json +17 -0
- hex_zmq_servers/config/cam_rgb.json +28 -0
- hex_zmq_servers/config/mujoco_archer_y6.json +37 -0
- hex_zmq_servers/config/mujoco_e3_desktop.json +41 -0
- hex_zmq_servers/config/robot_dummy.json +153 -0
- hex_zmq_servers/config/robot_gello.json +66 -0
- hex_zmq_servers/config/robot_hexarm.json +37 -0
- hex_zmq_servers/config/zmq_dummy.json +12 -0
- hex_zmq_servers/device_base.py +44 -0
- hex_zmq_servers/hex_launch.py +489 -0
- hex_zmq_servers/mujoco/__init__.py +28 -0
- hex_zmq_servers/mujoco/archer_y6/__init__.py +17 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/arm_base_link.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_1.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_2.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_3.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_4.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_5.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/assets.xml +17 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/camera_link.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_base_link.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_left_helper_link.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_left_link_1.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_left_link_2.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_right_helper_link.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_right_link_1.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_right_link_2.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/table_link.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/robot.xml +95 -0
- hex_zmq_servers/mujoco/archer_y6/model/scene.xml +51 -0
- hex_zmq_servers/mujoco/archer_y6/model/setting.xml +37 -0
- hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6.py +325 -0
- hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6_cli.py +71 -0
- hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6_srv.py +148 -0
- hex_zmq_servers/mujoco/e3_desktop/__init__.py +17 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_base_link.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_1.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_2.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_3.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_4.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_5.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/assets.xml +18 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/camera_link.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/e3_desktop_base_link.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_base_link.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_left_helper_link.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_left_link_1.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_left_link_2.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_right_helper_link.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_right_link_1.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_right_link_2.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/table_link.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/robot.xml +188 -0
- hex_zmq_servers/mujoco/e3_desktop/model/scene.xml +53 -0
- hex_zmq_servers/mujoco/e3_desktop/model/setting.xml +72 -0
- hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop.py +449 -0
- hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop_cli.py +289 -0
- hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop_srv.py +244 -0
- hex_zmq_servers/mujoco/mujoco_base.py +425 -0
- hex_zmq_servers/robot/__init__.py +37 -0
- hex_zmq_servers/robot/dummy/__init__.py +17 -0
- hex_zmq_servers/robot/dummy/robot_dummy.py +94 -0
- hex_zmq_servers/robot/dummy/robot_dummy_cli.py +29 -0
- hex_zmq_servers/robot/dummy/robot_dummy_srv.py +82 -0
- hex_zmq_servers/robot/gello/__init__.py +17 -0
- hex_zmq_servers/robot/gello/robot_gello.py +366 -0
- hex_zmq_servers/robot/gello/robot_gello_cli.py +29 -0
- hex_zmq_servers/robot/gello/robot_gello_srv.py +93 -0
- hex_zmq_servers/robot/hexarm/__init__.py +47 -0
- hex_zmq_servers/robot/hexarm/robot_hexarm.py +292 -0
- hex_zmq_servers/robot/hexarm/robot_hexarm_cli.py +37 -0
- hex_zmq_servers/robot/hexarm/robot_hexarm_srv.py +87 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_l6y/empty.urdf +206 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_l6y/gp100.urdf +206 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_l6y/gp100_handle.urdf +206 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_l6y/gp100_p050.urdf +206 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_l6y/gp100_p050_handle.urdf +206 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_y6/empty.urdf +207 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100.urdf +207 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100_handle.urdf +207 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100_p050.urdf +207 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100_p050_handle.urdf +207 -0
- hex_zmq_servers/robot/robot_base.py +276 -0
- hex_zmq_servers/zmq_base.py +547 -0
- hex_zmq_servers-0.3.9.dist-info/METADATA +147 -0
- hex_zmq_servers-0.3.9.dist-info/RECORD +110 -0
- hex_zmq_servers-0.3.9.dist-info/WHEEL +5 -0
- hex_zmq_servers-0.3.9.dist-info/licenses/LICENSE +201 -0
- hex_zmq_servers-0.3.9.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding:utf-8 -*-
|
|
3
|
+
################################################################
|
|
4
|
+
# Copyright 2025 Dong Zhaorui. All rights reserved.
|
|
5
|
+
# Author: Dong Zhaorui 847235539@qq.com
|
|
6
|
+
# Date : 2025-09-16
|
|
7
|
+
################################################################
|
|
8
|
+
|
|
9
|
+
import threading
|
|
10
|
+
import numpy as np
|
|
11
|
+
from collections import deque
|
|
12
|
+
from abc import abstractmethod
|
|
13
|
+
|
|
14
|
+
from ..device_base import HexDeviceBase
|
|
15
|
+
from ..zmq_base import (
|
|
16
|
+
hex_zmq_ts_now,
|
|
17
|
+
HexRate,
|
|
18
|
+
HexZMQClientBase,
|
|
19
|
+
HexZMQServerBase,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
NET_CONFIG = {
|
|
23
|
+
"ip": "127.0.0.1",
|
|
24
|
+
"port": 12345,
|
|
25
|
+
"realtime_mode": False,
|
|
26
|
+
"deque_maxlen": 10,
|
|
27
|
+
"client_timeout_ms": 200,
|
|
28
|
+
"server_timeout_ms": 1_000,
|
|
29
|
+
"server_num_workers": 4,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
TAU = 2 * np.pi
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class HexRobotBase(HexDeviceBase):
|
|
36
|
+
|
|
37
|
+
def __init__(self, realtime_mode: bool = False):
|
|
38
|
+
HexDeviceBase.__init__(self, realtime_mode)
|
|
39
|
+
self._dofs = None
|
|
40
|
+
self._limits = None
|
|
41
|
+
self._seq_clear_flag = False
|
|
42
|
+
|
|
43
|
+
def __del__(self):
|
|
44
|
+
HexDeviceBase.__del__(self)
|
|
45
|
+
|
|
46
|
+
def is_working(self) -> bool:
|
|
47
|
+
return self._working.is_set()
|
|
48
|
+
|
|
49
|
+
def get_dofs(self) -> np.ndarray:
|
|
50
|
+
self._wait_for_working()
|
|
51
|
+
return np.array(self._dofs, dtype=np.uint8)
|
|
52
|
+
|
|
53
|
+
def get_limits(self) -> np.ndarray:
|
|
54
|
+
self._wait_for_working()
|
|
55
|
+
return self._limits
|
|
56
|
+
|
|
57
|
+
@staticmethod
|
|
58
|
+
def _rads_normalize(rads: np.ndarray) -> np.ndarray:
|
|
59
|
+
return (rads + np.pi) % TAU - np.pi
|
|
60
|
+
|
|
61
|
+
@staticmethod
|
|
62
|
+
def _apply_pos_limits(
|
|
63
|
+
rads: np.ndarray,
|
|
64
|
+
lower_bound: np.ndarray,
|
|
65
|
+
upper_bound: np.ndarray,
|
|
66
|
+
) -> np.ndarray:
|
|
67
|
+
normed_rads = HexRobotBase._rads_normalize(rads)
|
|
68
|
+
outside = (normed_rads < lower_bound) | (normed_rads > upper_bound)
|
|
69
|
+
if not np.any(outside):
|
|
70
|
+
return normed_rads
|
|
71
|
+
|
|
72
|
+
lower_dist = np.fabs(
|
|
73
|
+
HexRobotBase._rads_normalize((normed_rads - lower_bound)[outside]))
|
|
74
|
+
upper_dist = np.fabs(
|
|
75
|
+
HexRobotBase._rads_normalize((normed_rads - upper_bound)[outside]))
|
|
76
|
+
choose_lower = lower_dist < upper_dist
|
|
77
|
+
choose_upper = ~choose_lower
|
|
78
|
+
|
|
79
|
+
outside_full = np.flatnonzero(outside)
|
|
80
|
+
outside_lower = outside_full[choose_lower]
|
|
81
|
+
outside_upper = outside_full[choose_upper]
|
|
82
|
+
normed_rads[outside_lower] = lower_bound[outside_lower]
|
|
83
|
+
normed_rads[outside_upper] = upper_bound[outside_upper]
|
|
84
|
+
|
|
85
|
+
return normed_rads
|
|
86
|
+
|
|
87
|
+
@abstractmethod
|
|
88
|
+
def work_loop(self, hex_queues: list[deque | threading.Event]):
|
|
89
|
+
raise NotImplementedError(
|
|
90
|
+
"`work_loop` should be implemented by the child class")
|
|
91
|
+
|
|
92
|
+
@abstractmethod
|
|
93
|
+
def close(self):
|
|
94
|
+
raise NotImplementedError(
|
|
95
|
+
"`close` should be implemented by the child class")
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class HexRobotClientBase(HexZMQClientBase):
|
|
99
|
+
|
|
100
|
+
def __init__(self, net_config: dict = NET_CONFIG):
|
|
101
|
+
HexZMQClientBase.__init__(self, net_config)
|
|
102
|
+
self._states_seq = 0
|
|
103
|
+
self._used_states_seq = 0
|
|
104
|
+
self._cmds_seq = 0
|
|
105
|
+
self._states_queue = deque(maxlen=self._deque_maxlen)
|
|
106
|
+
self._cmds_queue = deque(maxlen=self._deque_maxlen)
|
|
107
|
+
|
|
108
|
+
def __del__(self):
|
|
109
|
+
HexZMQClientBase.__del__(self)
|
|
110
|
+
|
|
111
|
+
def seq_clear(self):
|
|
112
|
+
clear_hdr, _ = self.request({"cmd": "seq_clear"})
|
|
113
|
+
return clear_hdr
|
|
114
|
+
|
|
115
|
+
def get_dofs(self):
|
|
116
|
+
_, dofs = self.request({"cmd": "get_dofs"})
|
|
117
|
+
return dofs
|
|
118
|
+
|
|
119
|
+
def get_limits(self):
|
|
120
|
+
_, limits = self.request({"cmd": "get_limits"})
|
|
121
|
+
return limits
|
|
122
|
+
|
|
123
|
+
def get_states(self, newest: bool = False):
|
|
124
|
+
try:
|
|
125
|
+
if self._realtime_mode or newest:
|
|
126
|
+
hdr, states = self._states_queue[-1]
|
|
127
|
+
if self._used_states_seq != hdr["args"]:
|
|
128
|
+
self._used_states_seq = hdr["args"]
|
|
129
|
+
return hdr, states
|
|
130
|
+
else:
|
|
131
|
+
return None, None
|
|
132
|
+
else:
|
|
133
|
+
return self._states_queue.popleft()
|
|
134
|
+
except IndexError:
|
|
135
|
+
return None, None
|
|
136
|
+
|
|
137
|
+
def set_cmds(self, cmds: np.ndarray):
|
|
138
|
+
self._cmds_queue.append(cmds)
|
|
139
|
+
|
|
140
|
+
def _get_states_inner(self):
|
|
141
|
+
hdr, states = self.request({
|
|
142
|
+
"cmd":
|
|
143
|
+
"get_states",
|
|
144
|
+
"args": (1 + self._states_seq) % self._max_seq_num,
|
|
145
|
+
})
|
|
146
|
+
try:
|
|
147
|
+
cmd = hdr["cmd"]
|
|
148
|
+
if cmd == "get_states_ok":
|
|
149
|
+
self._states_seq = hdr["args"]
|
|
150
|
+
return hdr, states
|
|
151
|
+
else:
|
|
152
|
+
return None, None
|
|
153
|
+
except KeyError:
|
|
154
|
+
print(f"\033[91m{hdr['cmd']} requires `cmd`\033[0m")
|
|
155
|
+
return None, None
|
|
156
|
+
except Exception as e:
|
|
157
|
+
print(f"\033[91mget_states failed: {e}\033[0m")
|
|
158
|
+
return None, None
|
|
159
|
+
|
|
160
|
+
def _set_cmds_inner(self, cmds: np.ndarray) -> bool:
|
|
161
|
+
hdr, _ = self.request(
|
|
162
|
+
{
|
|
163
|
+
"cmd": "set_cmds",
|
|
164
|
+
"ts": hex_zmq_ts_now(),
|
|
165
|
+
"args": self._cmds_seq,
|
|
166
|
+
},
|
|
167
|
+
cmds,
|
|
168
|
+
)
|
|
169
|
+
# print(f"set_cmds seq: {self._cmds_seq}")
|
|
170
|
+
try:
|
|
171
|
+
cmd = hdr["cmd"]
|
|
172
|
+
if cmd == "set_cmds_ok":
|
|
173
|
+
self._cmds_seq = (self._cmds_seq + 1) % self._max_seq_num
|
|
174
|
+
return True
|
|
175
|
+
else:
|
|
176
|
+
return False
|
|
177
|
+
except KeyError:
|
|
178
|
+
print(f"\033[91m{hdr['cmd']} requires `cmd`\033[0m")
|
|
179
|
+
return False
|
|
180
|
+
except Exception as e:
|
|
181
|
+
print(f"\033[91mset_cmds failed: {e}\033[0m")
|
|
182
|
+
return False
|
|
183
|
+
|
|
184
|
+
def _recv_loop(self):
|
|
185
|
+
rate = HexRate(2000)
|
|
186
|
+
while self._recv_flag:
|
|
187
|
+
hdr, states = self._get_states_inner()
|
|
188
|
+
if hdr is not None:
|
|
189
|
+
self._states_queue.append((hdr, states))
|
|
190
|
+
|
|
191
|
+
try:
|
|
192
|
+
cmds = self._cmds_queue[
|
|
193
|
+
-1] if self._realtime_mode else self._cmds_queue.popleft()
|
|
194
|
+
_ = self._set_cmds_inner(cmds)
|
|
195
|
+
except IndexError:
|
|
196
|
+
pass
|
|
197
|
+
|
|
198
|
+
rate.sleep()
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class HexRobotServerBase(HexZMQServerBase):
|
|
202
|
+
|
|
203
|
+
def __init__(self, net_config: dict = NET_CONFIG):
|
|
204
|
+
HexZMQServerBase.__init__(self, net_config)
|
|
205
|
+
self._device: HexDeviceBase = None
|
|
206
|
+
self._states_queue = deque(maxlen=self._deque_maxlen)
|
|
207
|
+
self._cmds_queue = deque(maxlen=self._deque_maxlen)
|
|
208
|
+
self._cmds_seq = -1
|
|
209
|
+
self._seq_clear_flag = False
|
|
210
|
+
|
|
211
|
+
def __del__(self):
|
|
212
|
+
HexZMQServerBase.__del__(self)
|
|
213
|
+
self._device.close()
|
|
214
|
+
|
|
215
|
+
def work_loop(self):
|
|
216
|
+
try:
|
|
217
|
+
self._device.work_loop([
|
|
218
|
+
self._states_queue,
|
|
219
|
+
self._cmds_queue,
|
|
220
|
+
self._stop_event,
|
|
221
|
+
])
|
|
222
|
+
finally:
|
|
223
|
+
self._device.close()
|
|
224
|
+
|
|
225
|
+
def _seq_clear(self):
|
|
226
|
+
self._seq_clear_flag = True
|
|
227
|
+
return True
|
|
228
|
+
|
|
229
|
+
def _get_states(self, recv_hdr: dict):
|
|
230
|
+
try:
|
|
231
|
+
seq = recv_hdr["args"]
|
|
232
|
+
except KeyError:
|
|
233
|
+
print(f"\033[91m{recv_hdr['cmd']} requires `args`\033[0m")
|
|
234
|
+
return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
|
|
235
|
+
|
|
236
|
+
try:
|
|
237
|
+
ts, count, states = self._states_queue[
|
|
238
|
+
-1] if self._realtime_mode else self._states_queue.popleft()
|
|
239
|
+
except IndexError:
|
|
240
|
+
return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
|
|
241
|
+
except Exception as e:
|
|
242
|
+
print(f"\033[91m{recv_hdr['cmd']} failed: {e}\033[0m")
|
|
243
|
+
return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
|
|
244
|
+
|
|
245
|
+
delta = (count - seq) % self._max_seq_num
|
|
246
|
+
if delta >= 0 and delta < 1e6:
|
|
247
|
+
return {
|
|
248
|
+
"cmd": f"{recv_hdr['cmd']}_ok",
|
|
249
|
+
"ts": ts,
|
|
250
|
+
"args": count
|
|
251
|
+
}, states
|
|
252
|
+
else:
|
|
253
|
+
return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
|
|
254
|
+
|
|
255
|
+
def _set_cmds(self, recv_hdr: dict, recv_buf: np.ndarray):
|
|
256
|
+
seq = recv_hdr.get("args", None)
|
|
257
|
+
if self._seq_clear_flag:
|
|
258
|
+
self._seq_clear_flag = False
|
|
259
|
+
self._cmds_seq = -1
|
|
260
|
+
return self.no_ts_hdr(recv_hdr, False), None
|
|
261
|
+
|
|
262
|
+
if seq is not None:
|
|
263
|
+
delta = (seq - self._cmds_seq) % self._max_seq_num
|
|
264
|
+
if delta >= 0 and delta < 1e6:
|
|
265
|
+
self._cmds_seq = seq
|
|
266
|
+
self._cmds_queue.append((recv_hdr["ts"], seq, recv_buf))
|
|
267
|
+
return self.no_ts_hdr(recv_hdr, True), None
|
|
268
|
+
else:
|
|
269
|
+
return self.no_ts_hdr(recv_hdr, False), None
|
|
270
|
+
else:
|
|
271
|
+
return self.no_ts_hdr(recv_hdr, False), None
|
|
272
|
+
|
|
273
|
+
@abstractmethod
|
|
274
|
+
def _process_request(self, recv_hdr: dict, recv_buf: np.ndarray):
|
|
275
|
+
raise NotImplementedError(
|
|
276
|
+
"`_process_request` should be implemented by the child class")
|