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,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")