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.
Files changed (110) hide show
  1. hex_zmq_servers/__init__.py +173 -0
  2. hex_zmq_servers/cam/__init__.py +52 -0
  3. hex_zmq_servers/cam/berxel/__init__.py +17 -0
  4. hex_zmq_servers/cam/berxel/cam_berxel.py +282 -0
  5. hex_zmq_servers/cam/berxel/cam_berxel_cli.py +33 -0
  6. hex_zmq_servers/cam/berxel/cam_berxel_srv.py +79 -0
  7. hex_zmq_servers/cam/cam_base.py +189 -0
  8. hex_zmq_servers/cam/dummy/__init__.py +17 -0
  9. hex_zmq_servers/cam/dummy/cam_dummy.py +69 -0
  10. hex_zmq_servers/cam/dummy/cam_dummy_cli.py +29 -0
  11. hex_zmq_servers/cam/dummy/cam_dummy_srv.py +68 -0
  12. hex_zmq_servers/cam/realsense/__init__.py +17 -0
  13. hex_zmq_servers/cam/realsense/cam_realsense.py +159 -0
  14. hex_zmq_servers/cam/realsense/cam_realsense_cli.py +33 -0
  15. hex_zmq_servers/cam/realsense/cam_realsense_srv.py +78 -0
  16. hex_zmq_servers/cam/rgb/__init__.py +17 -0
  17. hex_zmq_servers/cam/rgb/cam_rgb.py +135 -0
  18. hex_zmq_servers/cam/rgb/cam_rgb_cli.py +43 -0
  19. hex_zmq_servers/cam/rgb/cam_rgb_srv.py +78 -0
  20. hex_zmq_servers/config/cam_berxel.json +18 -0
  21. hex_zmq_servers/config/cam_dummy.json +12 -0
  22. hex_zmq_servers/config/cam_realsense.json +17 -0
  23. hex_zmq_servers/config/cam_rgb.json +28 -0
  24. hex_zmq_servers/config/mujoco_archer_y6.json +37 -0
  25. hex_zmq_servers/config/mujoco_e3_desktop.json +41 -0
  26. hex_zmq_servers/config/robot_dummy.json +153 -0
  27. hex_zmq_servers/config/robot_gello.json +66 -0
  28. hex_zmq_servers/config/robot_hexarm.json +37 -0
  29. hex_zmq_servers/config/zmq_dummy.json +12 -0
  30. hex_zmq_servers/device_base.py +44 -0
  31. hex_zmq_servers/hex_launch.py +489 -0
  32. hex_zmq_servers/mujoco/__init__.py +28 -0
  33. hex_zmq_servers/mujoco/archer_y6/__init__.py +17 -0
  34. hex_zmq_servers/mujoco/archer_y6/model/assets/arm_base_link.STL +0 -0
  35. hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_1.STL +0 -0
  36. hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_2.STL +0 -0
  37. hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_3.STL +0 -0
  38. hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_4.STL +0 -0
  39. hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_5.STL +0 -0
  40. hex_zmq_servers/mujoco/archer_y6/model/assets/assets.xml +17 -0
  41. hex_zmq_servers/mujoco/archer_y6/model/assets/camera_link.STL +0 -0
  42. hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_base_link.STL +0 -0
  43. hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_left_helper_link.STL +0 -0
  44. hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_left_link_1.STL +0 -0
  45. hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_left_link_2.STL +0 -0
  46. hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_right_helper_link.STL +0 -0
  47. hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_right_link_1.STL +0 -0
  48. hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_right_link_2.STL +0 -0
  49. hex_zmq_servers/mujoco/archer_y6/model/assets/table_link.STL +0 -0
  50. hex_zmq_servers/mujoco/archer_y6/model/robot.xml +95 -0
  51. hex_zmq_servers/mujoco/archer_y6/model/scene.xml +51 -0
  52. hex_zmq_servers/mujoco/archer_y6/model/setting.xml +37 -0
  53. hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6.py +325 -0
  54. hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6_cli.py +71 -0
  55. hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6_srv.py +148 -0
  56. hex_zmq_servers/mujoco/e3_desktop/__init__.py +17 -0
  57. hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_base_link.STL +0 -0
  58. hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_1.STL +0 -0
  59. hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_2.STL +0 -0
  60. hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_3.STL +0 -0
  61. hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_4.STL +0 -0
  62. hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_5.STL +0 -0
  63. hex_zmq_servers/mujoco/e3_desktop/model/assets/assets.xml +18 -0
  64. hex_zmq_servers/mujoco/e3_desktop/model/assets/camera_link.STL +0 -0
  65. hex_zmq_servers/mujoco/e3_desktop/model/assets/e3_desktop_base_link.STL +0 -0
  66. hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_base_link.STL +0 -0
  67. hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_left_helper_link.STL +0 -0
  68. hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_left_link_1.STL +0 -0
  69. hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_left_link_2.STL +0 -0
  70. hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_right_helper_link.STL +0 -0
  71. hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_right_link_1.STL +0 -0
  72. hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_right_link_2.STL +0 -0
  73. hex_zmq_servers/mujoco/e3_desktop/model/assets/table_link.STL +0 -0
  74. hex_zmq_servers/mujoco/e3_desktop/model/robot.xml +188 -0
  75. hex_zmq_servers/mujoco/e3_desktop/model/scene.xml +53 -0
  76. hex_zmq_servers/mujoco/e3_desktop/model/setting.xml +72 -0
  77. hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop.py +449 -0
  78. hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop_cli.py +289 -0
  79. hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop_srv.py +244 -0
  80. hex_zmq_servers/mujoco/mujoco_base.py +425 -0
  81. hex_zmq_servers/robot/__init__.py +37 -0
  82. hex_zmq_servers/robot/dummy/__init__.py +17 -0
  83. hex_zmq_servers/robot/dummy/robot_dummy.py +94 -0
  84. hex_zmq_servers/robot/dummy/robot_dummy_cli.py +29 -0
  85. hex_zmq_servers/robot/dummy/robot_dummy_srv.py +82 -0
  86. hex_zmq_servers/robot/gello/__init__.py +17 -0
  87. hex_zmq_servers/robot/gello/robot_gello.py +366 -0
  88. hex_zmq_servers/robot/gello/robot_gello_cli.py +29 -0
  89. hex_zmq_servers/robot/gello/robot_gello_srv.py +93 -0
  90. hex_zmq_servers/robot/hexarm/__init__.py +47 -0
  91. hex_zmq_servers/robot/hexarm/robot_hexarm.py +292 -0
  92. hex_zmq_servers/robot/hexarm/robot_hexarm_cli.py +37 -0
  93. hex_zmq_servers/robot/hexarm/robot_hexarm_srv.py +87 -0
  94. hex_zmq_servers/robot/hexarm/urdf/archer_l6y/empty.urdf +206 -0
  95. hex_zmq_servers/robot/hexarm/urdf/archer_l6y/gp100.urdf +206 -0
  96. hex_zmq_servers/robot/hexarm/urdf/archer_l6y/gp100_handle.urdf +206 -0
  97. hex_zmq_servers/robot/hexarm/urdf/archer_l6y/gp100_p050.urdf +206 -0
  98. hex_zmq_servers/robot/hexarm/urdf/archer_l6y/gp100_p050_handle.urdf +206 -0
  99. hex_zmq_servers/robot/hexarm/urdf/archer_y6/empty.urdf +207 -0
  100. hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100.urdf +207 -0
  101. hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100_handle.urdf +207 -0
  102. hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100_p050.urdf +207 -0
  103. hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100_p050_handle.urdf +207 -0
  104. hex_zmq_servers/robot/robot_base.py +276 -0
  105. hex_zmq_servers/zmq_base.py +547 -0
  106. hex_zmq_servers-0.3.9.dist-info/METADATA +147 -0
  107. hex_zmq_servers-0.3.9.dist-info/RECORD +110 -0
  108. hex_zmq_servers-0.3.9.dist-info/WHEEL +5 -0
  109. hex_zmq_servers-0.3.9.dist-info/licenses/LICENSE +201 -0
  110. 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)