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,289 @@
|
|
|
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-12
|
|
7
|
+
################################################################
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
from collections import deque
|
|
11
|
+
from ...zmq_base import HexRate, hex_zmq_ts_now
|
|
12
|
+
from ..mujoco_base import HexMujocoClientBase
|
|
13
|
+
|
|
14
|
+
NET_CONFIG = {
|
|
15
|
+
"ip": "127.0.0.1",
|
|
16
|
+
"port": 12345,
|
|
17
|
+
"realtime_mode": False,
|
|
18
|
+
"deque_maxlen": 10,
|
|
19
|
+
"client_timeout_ms": 200,
|
|
20
|
+
"server_timeout_ms": 1_000,
|
|
21
|
+
"server_num_workers": 4,
|
|
22
|
+
}
|
|
23
|
+
RECV_CONFIG = {
|
|
24
|
+
"head_rgb": True,
|
|
25
|
+
"head_depth": True,
|
|
26
|
+
"left_rgb": True,
|
|
27
|
+
"left_depth": True,
|
|
28
|
+
"right_rgb": True,
|
|
29
|
+
"right_depth": True,
|
|
30
|
+
"obj": True,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class HexMujocoE3DesktopClient(HexMujocoClientBase):
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
net_config: dict = NET_CONFIG,
|
|
39
|
+
recv_config: dict = RECV_CONFIG,
|
|
40
|
+
):
|
|
41
|
+
HexMujocoClientBase.__init__(self, net_config)
|
|
42
|
+
self.__recv_config = recv_config
|
|
43
|
+
self._states_seq = {
|
|
44
|
+
"left": 0,
|
|
45
|
+
"right": 0,
|
|
46
|
+
"obj": 0,
|
|
47
|
+
}
|
|
48
|
+
self._used_states_queue = {
|
|
49
|
+
"left": 0,
|
|
50
|
+
"right": 0,
|
|
51
|
+
"obj": 0,
|
|
52
|
+
}
|
|
53
|
+
self._states_queue = {
|
|
54
|
+
"left": deque(maxlen=self._deque_maxlen),
|
|
55
|
+
"right": deque(maxlen=self._deque_maxlen),
|
|
56
|
+
"obj": deque(maxlen=self._deque_maxlen),
|
|
57
|
+
}
|
|
58
|
+
self._camera_seq = {
|
|
59
|
+
"head_rgb": 0,
|
|
60
|
+
"head_depth": 0,
|
|
61
|
+
"left_rgb": 0,
|
|
62
|
+
"left_depth": 0,
|
|
63
|
+
"right_rgb": 0,
|
|
64
|
+
"right_depth": 0,
|
|
65
|
+
}
|
|
66
|
+
self._used_camera_seq = {
|
|
67
|
+
"head_rgb": 0,
|
|
68
|
+
"head_depth": 0,
|
|
69
|
+
"left_rgb": 0,
|
|
70
|
+
"left_depth": 0,
|
|
71
|
+
"right_rgb": 0,
|
|
72
|
+
"right_depth": 0,
|
|
73
|
+
}
|
|
74
|
+
self._camera_queue = {
|
|
75
|
+
"head_rgb": deque(maxlen=self._deque_maxlen),
|
|
76
|
+
"head_depth": deque(maxlen=self._deque_maxlen),
|
|
77
|
+
"left_rgb": deque(maxlen=self._deque_maxlen),
|
|
78
|
+
"left_depth": deque(maxlen=self._deque_maxlen),
|
|
79
|
+
"right_rgb": deque(maxlen=self._deque_maxlen),
|
|
80
|
+
"right_depth": deque(maxlen=self._deque_maxlen),
|
|
81
|
+
}
|
|
82
|
+
self._cmds_seq = {
|
|
83
|
+
"left": 0,
|
|
84
|
+
"right": 0,
|
|
85
|
+
}
|
|
86
|
+
self._cmds_queue = {
|
|
87
|
+
"left": deque(maxlen=self._deque_maxlen),
|
|
88
|
+
"right": deque(maxlen=self._deque_maxlen),
|
|
89
|
+
}
|
|
90
|
+
self._wait_for_working()
|
|
91
|
+
|
|
92
|
+
def reset(self):
|
|
93
|
+
HexMujocoClientBase.reset(self)
|
|
94
|
+
self._states_seq = {
|
|
95
|
+
"left": 0,
|
|
96
|
+
"right": 0,
|
|
97
|
+
"obj": 0,
|
|
98
|
+
}
|
|
99
|
+
self._used_states_queue = {
|
|
100
|
+
"left": 0,
|
|
101
|
+
"right": 0,
|
|
102
|
+
"obj": 0,
|
|
103
|
+
}
|
|
104
|
+
self._camera_seq = {
|
|
105
|
+
"head_rgb": 0,
|
|
106
|
+
"head_depth": 0,
|
|
107
|
+
"left_rgb": 0,
|
|
108
|
+
"left_depth": 0,
|
|
109
|
+
"right_rgb": 0,
|
|
110
|
+
"right_depth": 0,
|
|
111
|
+
}
|
|
112
|
+
self._used_camera_seq = {
|
|
113
|
+
"head_rgb": 0,
|
|
114
|
+
"head_depth": 0,
|
|
115
|
+
"left_rgb": 0,
|
|
116
|
+
"left_depth": 0,
|
|
117
|
+
"right_rgb": 0,
|
|
118
|
+
"right_depth": 0,
|
|
119
|
+
}
|
|
120
|
+
self._cmds_seq = {
|
|
121
|
+
"left": 0,
|
|
122
|
+
"right": 0,
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
def get_rgb(self, camera_name: str | None = None, newest: bool = False):
|
|
126
|
+
name = f"{camera_name}_rgb"
|
|
127
|
+
try:
|
|
128
|
+
if self._realtime_mode or newest:
|
|
129
|
+
hdr, img = self._camera_queue[name][-1]
|
|
130
|
+
if self._used_camera_seq[name] != hdr["args"]:
|
|
131
|
+
self._used_camera_seq[name] = hdr["args"]
|
|
132
|
+
return hdr, img
|
|
133
|
+
else:
|
|
134
|
+
return None, None
|
|
135
|
+
else:
|
|
136
|
+
return self._camera_queue[name].popleft()
|
|
137
|
+
except IndexError:
|
|
138
|
+
return None, None
|
|
139
|
+
except KeyError:
|
|
140
|
+
print(f"\033[91munknown camera name: {name}\033[0m")
|
|
141
|
+
return None, None
|
|
142
|
+
|
|
143
|
+
def get_depth(self, camera_name: str | None = None, newest: bool = False):
|
|
144
|
+
name = f"{camera_name}_depth"
|
|
145
|
+
try:
|
|
146
|
+
if self._realtime_mode or newest:
|
|
147
|
+
hdr, img = self._camera_queue[name][-1]
|
|
148
|
+
if self._used_camera_seq[name] != hdr["args"]:
|
|
149
|
+
self._used_camera_seq[name] = hdr["args"]
|
|
150
|
+
return hdr, img
|
|
151
|
+
else:
|
|
152
|
+
return None, None
|
|
153
|
+
else:
|
|
154
|
+
return self._camera_queue[name].popleft()
|
|
155
|
+
except IndexError:
|
|
156
|
+
return None, None
|
|
157
|
+
except KeyError:
|
|
158
|
+
print(f"\033[91munknown camera name: {name}\033[0m")
|
|
159
|
+
return None, None
|
|
160
|
+
|
|
161
|
+
def set_cmds(
|
|
162
|
+
self,
|
|
163
|
+
cmds: np.ndarray,
|
|
164
|
+
robot_name: str | None = None,
|
|
165
|
+
):
|
|
166
|
+
self._cmds_queue[robot_name].append(cmds)
|
|
167
|
+
|
|
168
|
+
def _process_frame(
|
|
169
|
+
self,
|
|
170
|
+
camera_name: str | None = None,
|
|
171
|
+
depth_flag: bool = False,
|
|
172
|
+
):
|
|
173
|
+
if camera_name is None:
|
|
174
|
+
raise ValueError("camera_name is required")
|
|
175
|
+
|
|
176
|
+
req_cmd = f"get_{'depth' if depth_flag else 'rgb'}_{camera_name}"
|
|
177
|
+
seq_key = f"{camera_name}_{'depth' if depth_flag else 'rgb'}"
|
|
178
|
+
|
|
179
|
+
hdr, img = self.request({
|
|
180
|
+
"cmd":
|
|
181
|
+
req_cmd,
|
|
182
|
+
"args": (1 + self._camera_seq[seq_key]) % self._max_seq_num,
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
try:
|
|
186
|
+
cmd = hdr["cmd"]
|
|
187
|
+
if cmd == f"{req_cmd}_ok":
|
|
188
|
+
self._camera_seq[seq_key] = hdr["args"]
|
|
189
|
+
return hdr, img
|
|
190
|
+
else:
|
|
191
|
+
return None, None
|
|
192
|
+
except KeyError:
|
|
193
|
+
print(f"\033[91m{hdr['cmd']} requires `cmd`\033[0m")
|
|
194
|
+
return None, None
|
|
195
|
+
except Exception as e:
|
|
196
|
+
print(f"\033[91m__process_frame failed: {e}\033[0m")
|
|
197
|
+
return None, None
|
|
198
|
+
|
|
199
|
+
def _set_cmds_inner(
|
|
200
|
+
self,
|
|
201
|
+
cmds: np.ndarray,
|
|
202
|
+
robot_name: str | None = None,
|
|
203
|
+
) -> bool:
|
|
204
|
+
req_cmd = "set_cmds"
|
|
205
|
+
if robot_name is not None:
|
|
206
|
+
req_cmd += f"_{robot_name}"
|
|
207
|
+
hdr, _ = self.request(
|
|
208
|
+
{
|
|
209
|
+
"cmd": req_cmd,
|
|
210
|
+
"ts": hex_zmq_ts_now(),
|
|
211
|
+
"args": self._cmds_seq[robot_name],
|
|
212
|
+
},
|
|
213
|
+
cmds,
|
|
214
|
+
)
|
|
215
|
+
# print(f"{req_cmd} seq: {self._cmds_seq[robot_name]}")
|
|
216
|
+
try:
|
|
217
|
+
cmd = hdr["cmd"]
|
|
218
|
+
if cmd == f"{req_cmd}_ok":
|
|
219
|
+
self._cmds_seq[robot_name] = (self._cmds_seq[robot_name] +
|
|
220
|
+
1) % self._max_seq_num
|
|
221
|
+
return True
|
|
222
|
+
else:
|
|
223
|
+
return False
|
|
224
|
+
except KeyError:
|
|
225
|
+
print(f"\033[91m{hdr['cmd']} requires `cmd`\033[0m")
|
|
226
|
+
return False
|
|
227
|
+
except Exception as e:
|
|
228
|
+
print(f"\033[91m{req_cmd} failed: {e}\033[0m")
|
|
229
|
+
return False
|
|
230
|
+
|
|
231
|
+
def _recv_loop(self):
|
|
232
|
+
rate = HexRate(2000)
|
|
233
|
+
image_trig_cnt = 0
|
|
234
|
+
while self._recv_flag:
|
|
235
|
+
hdr, states = self._get_states_inner("left")
|
|
236
|
+
if hdr is not None:
|
|
237
|
+
self._states_queue["left"].append((hdr, states))
|
|
238
|
+
hdr, states = self._get_states_inner("right")
|
|
239
|
+
if hdr is not None:
|
|
240
|
+
self._states_queue["right"].append((hdr, states))
|
|
241
|
+
if self.__recv_config["obj"]:
|
|
242
|
+
hdr, obj_pose = self._get_states_inner("obj")
|
|
243
|
+
if hdr is not None:
|
|
244
|
+
self._states_queue["obj"].append((hdr, obj_pose))
|
|
245
|
+
|
|
246
|
+
image_trig_cnt += 1
|
|
247
|
+
if image_trig_cnt >= 10:
|
|
248
|
+
image_trig_cnt = 0
|
|
249
|
+
if self.__recv_config["head_rgb"]:
|
|
250
|
+
hdr, img = self._get_rgb_inner("head")
|
|
251
|
+
if hdr is not None:
|
|
252
|
+
self._camera_queue["head_rgb"].append((hdr, img))
|
|
253
|
+
if self.__recv_config["head_depth"]:
|
|
254
|
+
hdr, img = self._get_depth_inner("head")
|
|
255
|
+
if hdr is not None:
|
|
256
|
+
self._camera_queue["head_depth"].append((hdr, img))
|
|
257
|
+
if self.__recv_config["left_rgb"]:
|
|
258
|
+
hdr, img = self._get_rgb_inner("left")
|
|
259
|
+
if hdr is not None:
|
|
260
|
+
self._camera_queue["left_rgb"].append((hdr, img))
|
|
261
|
+
if self.__recv_config["left_depth"]:
|
|
262
|
+
hdr, img = self._get_depth_inner("left")
|
|
263
|
+
if hdr is not None:
|
|
264
|
+
self._camera_queue["left_depth"].append((hdr, img))
|
|
265
|
+
if self.__recv_config["right_rgb"]:
|
|
266
|
+
hdr, img = self._get_rgb_inner("right")
|
|
267
|
+
if hdr is not None:
|
|
268
|
+
self._camera_queue["right_rgb"].append((hdr, img))
|
|
269
|
+
if self.__recv_config["right_depth"]:
|
|
270
|
+
hdr, img = self._get_depth_inner("right")
|
|
271
|
+
if hdr is not None:
|
|
272
|
+
self._camera_queue["right_depth"].append((hdr, img))
|
|
273
|
+
|
|
274
|
+
try:
|
|
275
|
+
cmds = self._cmds_queue["left"][
|
|
276
|
+
-1] if self._realtime_mode else self._cmds_queue[
|
|
277
|
+
"left"].popleft()
|
|
278
|
+
_ = self._set_cmds_inner(cmds, "left")
|
|
279
|
+
except IndexError:
|
|
280
|
+
pass
|
|
281
|
+
try:
|
|
282
|
+
cmds = self._cmds_queue["right"][
|
|
283
|
+
-1] if self._realtime_mode else self._cmds_queue[
|
|
284
|
+
"right"].popleft()
|
|
285
|
+
_ = self._set_cmds_inner(cmds, "right")
|
|
286
|
+
except IndexError:
|
|
287
|
+
pass
|
|
288
|
+
|
|
289
|
+
rate.sleep()
|
|
@@ -0,0 +1,244 @@
|
|
|
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 numpy as np
|
|
10
|
+
from collections import deque
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
from ..mujoco_base import HexMujocoServerBase
|
|
14
|
+
from .mujoco_e3_desktop import HexMujocoE3Desktop
|
|
15
|
+
except (ImportError, ValueError):
|
|
16
|
+
import sys
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
this_file = Path(__file__).resolve()
|
|
19
|
+
project_root = this_file.parents[3]
|
|
20
|
+
if str(project_root) not in sys.path:
|
|
21
|
+
sys.path.insert(0, str(project_root))
|
|
22
|
+
from hex_zmq_servers.mujoco.mujoco_base import HexMujocoServerBase
|
|
23
|
+
from hex_zmq_servers.mujoco.e3_desktop.mujoco_e3_desktop import HexMujocoE3Desktop
|
|
24
|
+
|
|
25
|
+
NET_CONFIG = {
|
|
26
|
+
"ip": "127.0.0.1",
|
|
27
|
+
"port": 12345,
|
|
28
|
+
"realtime_mode": False,
|
|
29
|
+
"deque_maxlen": 10,
|
|
30
|
+
"client_timeout_ms": 200,
|
|
31
|
+
"server_timeout_ms": 1_000,
|
|
32
|
+
"server_num_workers": 4,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
MUJOCO_CONFIG = {
|
|
36
|
+
"states_rate": 1000,
|
|
37
|
+
"img_rate": 30,
|
|
38
|
+
"headless": False,
|
|
39
|
+
"sens_ts": True,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class HexMujocoE3DesktopServer(HexMujocoServerBase):
|
|
44
|
+
|
|
45
|
+
def __init__(
|
|
46
|
+
self,
|
|
47
|
+
net_config: dict = NET_CONFIG,
|
|
48
|
+
params_config: dict = MUJOCO_CONFIG,
|
|
49
|
+
):
|
|
50
|
+
HexMujocoServerBase.__init__(self, net_config)
|
|
51
|
+
|
|
52
|
+
# mujoco
|
|
53
|
+
self._device = HexMujocoE3Desktop(
|
|
54
|
+
params_config, net_config.get("realtime_mode", False))
|
|
55
|
+
|
|
56
|
+
# values
|
|
57
|
+
self._cmds_left_seq = -1
|
|
58
|
+
self._cmds_right_seq = -1
|
|
59
|
+
self._states_left_queue = deque(maxlen=self._deque_maxlen)
|
|
60
|
+
self._states_right_queue = deque(maxlen=self._deque_maxlen)
|
|
61
|
+
self._states_obj_queue = deque(maxlen=self._deque_maxlen)
|
|
62
|
+
self._cmds_left_queue = deque(maxlen=self._deque_maxlen)
|
|
63
|
+
self._cmds_right_queue = deque(maxlen=self._deque_maxlen)
|
|
64
|
+
self._rgb_head_queue = deque(maxlen=self._deque_maxlen)
|
|
65
|
+
self._depth_head_queue = deque(maxlen=self._deque_maxlen)
|
|
66
|
+
self._rgb_left_queue = deque(maxlen=self._deque_maxlen)
|
|
67
|
+
self._depth_left_queue = deque(maxlen=self._deque_maxlen)
|
|
68
|
+
self._rgb_right_queue = deque(maxlen=self._deque_maxlen)
|
|
69
|
+
self._depth_right_queue = deque(maxlen=self._deque_maxlen)
|
|
70
|
+
|
|
71
|
+
def work_loop(self):
|
|
72
|
+
try:
|
|
73
|
+
self._device.work_loop([
|
|
74
|
+
self._states_left_queue,
|
|
75
|
+
self._states_right_queue,
|
|
76
|
+
self._states_obj_queue,
|
|
77
|
+
self._cmds_left_queue,
|
|
78
|
+
self._cmds_right_queue,
|
|
79
|
+
self._rgb_head_queue,
|
|
80
|
+
self._depth_head_queue,
|
|
81
|
+
self._rgb_left_queue,
|
|
82
|
+
self._depth_left_queue,
|
|
83
|
+
self._rgb_right_queue,
|
|
84
|
+
self._depth_right_queue,
|
|
85
|
+
self._stop_event,
|
|
86
|
+
])
|
|
87
|
+
finally:
|
|
88
|
+
self._device.close()
|
|
89
|
+
|
|
90
|
+
def _get_states(self, recv_hdr: dict):
|
|
91
|
+
try:
|
|
92
|
+
seq = recv_hdr["args"]
|
|
93
|
+
except KeyError:
|
|
94
|
+
print(f"\033[91m{recv_hdr['cmd']} requires `args`\033[0m")
|
|
95
|
+
return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
|
|
96
|
+
|
|
97
|
+
# get robot name
|
|
98
|
+
robot_name = recv_hdr["cmd"].split("_")[2]
|
|
99
|
+
if robot_name == "left":
|
|
100
|
+
queue = self._states_left_queue
|
|
101
|
+
elif robot_name == "right":
|
|
102
|
+
queue = self._states_right_queue
|
|
103
|
+
elif robot_name == "obj":
|
|
104
|
+
queue = self._states_obj_queue
|
|
105
|
+
else:
|
|
106
|
+
raise ValueError(f"unknown robot name: {robot_name}")
|
|
107
|
+
|
|
108
|
+
try:
|
|
109
|
+
ts, count, states = queue[
|
|
110
|
+
-1] if self._realtime_mode else queue.popleft()
|
|
111
|
+
except IndexError:
|
|
112
|
+
return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
|
|
113
|
+
except Exception as e:
|
|
114
|
+
print(f"\033[91m{recv_hdr['cmd']} failed: {e}\033[0m")
|
|
115
|
+
return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
|
|
116
|
+
|
|
117
|
+
delta = (count - seq) % self._max_seq_num
|
|
118
|
+
if delta >= 0 and delta < 1e6:
|
|
119
|
+
return {
|
|
120
|
+
"cmd": f"{recv_hdr['cmd']}_ok",
|
|
121
|
+
"ts": ts,
|
|
122
|
+
"args": count
|
|
123
|
+
}, states
|
|
124
|
+
else:
|
|
125
|
+
return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
|
|
126
|
+
|
|
127
|
+
def _set_cmds(self, recv_hdr: dict, recv_buf: np.ndarray):
|
|
128
|
+
seq = recv_hdr.get("args", None)
|
|
129
|
+
if self._seq_clear_flag:
|
|
130
|
+
self._seq_clear_flag = False
|
|
131
|
+
self._cmds_left_seq = -1
|
|
132
|
+
self._cmds_right_seq = -1
|
|
133
|
+
return self.no_ts_hdr(recv_hdr, False), None
|
|
134
|
+
|
|
135
|
+
# get robot name
|
|
136
|
+
robot_name = recv_hdr["cmd"].split("_")[2]
|
|
137
|
+
if robot_name == "left":
|
|
138
|
+
queue = self._cmds_left_queue
|
|
139
|
+
cmds_seq = self._cmds_left_seq
|
|
140
|
+
elif robot_name == "right":
|
|
141
|
+
queue = self._cmds_right_queue
|
|
142
|
+
cmds_seq = self._cmds_right_seq
|
|
143
|
+
else:
|
|
144
|
+
raise ValueError(f"unknown robot name: {robot_name}")
|
|
145
|
+
|
|
146
|
+
if seq is not None and seq > cmds_seq:
|
|
147
|
+
delta = (seq - cmds_seq) % self._max_seq_num
|
|
148
|
+
if delta >= 0 and delta < 1e6:
|
|
149
|
+
if robot_name == "left":
|
|
150
|
+
self._cmds_left_seq = cmds_seq
|
|
151
|
+
elif robot_name == "right":
|
|
152
|
+
self._cmds_right_seq = cmds_seq
|
|
153
|
+
queue.append((recv_hdr["ts"], seq, recv_buf))
|
|
154
|
+
return self.no_ts_hdr(recv_hdr, True), None
|
|
155
|
+
else:
|
|
156
|
+
return self.no_ts_hdr(recv_hdr, False), None
|
|
157
|
+
else:
|
|
158
|
+
return self.no_ts_hdr(recv_hdr, False), None
|
|
159
|
+
|
|
160
|
+
def _get_frame(self, recv_hdr: dict):
|
|
161
|
+
try:
|
|
162
|
+
seq = recv_hdr["args"]
|
|
163
|
+
except KeyError:
|
|
164
|
+
print(f"\033[91m{recv_hdr['cmd']} requires `args`\033[0m")
|
|
165
|
+
return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
|
|
166
|
+
|
|
167
|
+
# get camera config
|
|
168
|
+
split_cmd = recv_hdr["cmd"].split("_")
|
|
169
|
+
depth_flag = split_cmd[1] == "depth"
|
|
170
|
+
camera_name = split_cmd[2]
|
|
171
|
+
if camera_name == "head":
|
|
172
|
+
queue = self._rgb_head_queue if not depth_flag else self._depth_head_queue
|
|
173
|
+
elif camera_name == "left":
|
|
174
|
+
queue = self._rgb_left_queue if not depth_flag else self._depth_left_queue
|
|
175
|
+
elif camera_name == "right":
|
|
176
|
+
queue = self._rgb_right_queue if not depth_flag else self._depth_right_queue
|
|
177
|
+
else:
|
|
178
|
+
raise ValueError(f"unknown camera name: {camera_name}")
|
|
179
|
+
|
|
180
|
+
try:
|
|
181
|
+
ts, count, img = queue[
|
|
182
|
+
-1] if self._realtime_mode else queue.popleft()
|
|
183
|
+
except IndexError:
|
|
184
|
+
return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
|
|
185
|
+
except Exception as e:
|
|
186
|
+
print(f"\033[91m{recv_hdr['cmd']} failed: {e}\033[0m")
|
|
187
|
+
return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
|
|
188
|
+
|
|
189
|
+
delta = (count - seq) % self._max_seq_num
|
|
190
|
+
if delta >= 0 and delta < 1e6:
|
|
191
|
+
return {
|
|
192
|
+
"cmd": f"{recv_hdr['cmd']}_ok",
|
|
193
|
+
"ts": ts,
|
|
194
|
+
"args": count
|
|
195
|
+
}, img
|
|
196
|
+
else:
|
|
197
|
+
return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
|
|
198
|
+
|
|
199
|
+
def _process_request(self, recv_hdr: dict, recv_buf: np.ndarray):
|
|
200
|
+
if recv_hdr["cmd"] == "is_working":
|
|
201
|
+
return self.no_ts_hdr(recv_hdr, self._device.is_working()), None
|
|
202
|
+
elif recv_hdr["cmd"] == "seq_clear":
|
|
203
|
+
return self.no_ts_hdr(recv_hdr, self._seq_clear()), None
|
|
204
|
+
elif recv_hdr["cmd"] == "reset":
|
|
205
|
+
return self.no_ts_hdr(recv_hdr, self._device.reset()), None
|
|
206
|
+
elif recv_hdr["cmd"] == "get_dofs":
|
|
207
|
+
dofs = self._device.get_dofs()
|
|
208
|
+
return self.no_ts_hdr(recv_hdr, dofs is not None), dofs
|
|
209
|
+
elif recv_hdr["cmd"] == "get_limits":
|
|
210
|
+
limits = self._device.get_limits()
|
|
211
|
+
return self.no_ts_hdr(recv_hdr, limits is not None), limits
|
|
212
|
+
elif (recv_hdr["cmd"] == "set_cmds_left") or (recv_hdr["cmd"]
|
|
213
|
+
== "set_cmds_right"):
|
|
214
|
+
return self._set_cmds(recv_hdr, recv_buf)
|
|
215
|
+
elif (recv_hdr["cmd"] == "get_states_left") or (
|
|
216
|
+
recv_hdr["cmd"]
|
|
217
|
+
== "get_states_right") or (recv_hdr["cmd"]
|
|
218
|
+
== "get_states_obj"):
|
|
219
|
+
return self._get_states(recv_hdr)
|
|
220
|
+
elif recv_hdr["cmd"] == "get_intri":
|
|
221
|
+
intri = self._device.get_intri()
|
|
222
|
+
return self.no_ts_hdr(recv_hdr, intri is not None), intri
|
|
223
|
+
elif (recv_hdr["cmd"]
|
|
224
|
+
== "get_rgb_head") or (recv_hdr["cmd"] == "get_depth_head") or (
|
|
225
|
+
recv_hdr["cmd"] == "get_rgb_left") or (
|
|
226
|
+
recv_hdr["cmd"] == "get_depth_left") or (
|
|
227
|
+
recv_hdr["cmd"]
|
|
228
|
+
== "get_rgb_right") or (recv_hdr["cmd"]
|
|
229
|
+
== "get_depth_right"):
|
|
230
|
+
return self._get_frame(recv_hdr)
|
|
231
|
+
else:
|
|
232
|
+
raise ValueError(f"unknown command: {recv_hdr['cmd']}")
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
if __name__ == "__main__":
|
|
236
|
+
import argparse, json
|
|
237
|
+
from hex_zmq_servers.zmq_base import hex_server_helper
|
|
238
|
+
|
|
239
|
+
parser = argparse.ArgumentParser()
|
|
240
|
+
parser.add_argument("--cfg", type=str, required=True)
|
|
241
|
+
args = parser.parse_args()
|
|
242
|
+
cfg = json.loads(args.cfg)
|
|
243
|
+
|
|
244
|
+
hex_server_helper(cfg, HexMujocoE3DesktopServer)
|