hex-zmq-servers 0.3.2__py3-none-any.whl → 0.3.4__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 (45) hide show
  1. hex_zmq_servers/__init__.py +45 -20
  2. hex_zmq_servers/cam/__init__.py +29 -5
  3. hex_zmq_servers/cam/berxel/cam_berxel.py +8 -10
  4. hex_zmq_servers/cam/berxel/cam_berxel_cli.py +1 -0
  5. hex_zmq_servers/cam/cam_base.py +40 -10
  6. hex_zmq_servers/cam/dummy/cam_dummy.py +7 -7
  7. hex_zmq_servers/cam/dummy/cam_dummy_cli.py +1 -0
  8. hex_zmq_servers/cam/realsense/__init__.py +17 -0
  9. hex_zmq_servers/cam/realsense/cam_realsense.py +157 -0
  10. hex_zmq_servers/cam/realsense/cam_realsense_cli.py +31 -0
  11. hex_zmq_servers/cam/realsense/cam_realsense_srv.py +75 -0
  12. hex_zmq_servers/cam/rgb/__init__.py +17 -0
  13. hex_zmq_servers/cam/rgb/cam_rgb.py +133 -0
  14. hex_zmq_servers/cam/rgb/cam_rgb_cli.py +41 -0
  15. hex_zmq_servers/cam/rgb/cam_rgb_srv.py +75 -0
  16. hex_zmq_servers/config/cam_realsense.json +15 -0
  17. hex_zmq_servers/config/cam_rgb.json +26 -0
  18. hex_zmq_servers/config/mujoco_archer_y6.json +2 -1
  19. hex_zmq_servers/config/mujoco_e3_desktop.json +6 -1
  20. hex_zmq_servers/config/robot_hexarm.json +1 -1
  21. hex_zmq_servers/device_base.py +3 -2
  22. hex_zmq_servers/mujoco/archer_y6/model/robot.xml +6 -6
  23. hex_zmq_servers/mujoco/archer_y6/model/scene.xml +1 -1
  24. hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6.py +74 -39
  25. hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6_cli.py +42 -0
  26. hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6_srv.py +16 -14
  27. hex_zmq_servers/mujoco/e3_desktop/model/robot.xml +12 -12
  28. hex_zmq_servers/mujoco/e3_desktop/model/scene.xml +1 -1
  29. hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop.py +138 -70
  30. hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop_cli.py +148 -33
  31. hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop_srv.py +39 -35
  32. hex_zmq_servers/mujoco/mujoco_base.py +101 -64
  33. hex_zmq_servers/robot/dummy/robot_dummy.py +11 -7
  34. hex_zmq_servers/robot/dummy/robot_dummy_cli.py +1 -0
  35. hex_zmq_servers/robot/gello/robot_gello.py +11 -7
  36. hex_zmq_servers/robot/gello/robot_gello_cli.py +1 -0
  37. hex_zmq_servers/robot/hexarm/robot_hexarm.py +56 -22
  38. hex_zmq_servers/robot/hexarm/robot_hexarm_cli.py +1 -0
  39. hex_zmq_servers/robot/robot_base.py +40 -10
  40. hex_zmq_servers/zmq_base.py +97 -33
  41. {hex_zmq_servers-0.3.2.dist-info → hex_zmq_servers-0.3.4.dist-info}/METADATA +7 -6
  42. {hex_zmq_servers-0.3.2.dist-info → hex_zmq_servers-0.3.4.dist-info}/RECORD +45 -35
  43. {hex_zmq_servers-0.3.2.dist-info → hex_zmq_servers-0.3.4.dist-info}/WHEEL +0 -0
  44. {hex_zmq_servers-0.3.2.dist-info → hex_zmq_servers-0.3.4.dist-info}/licenses/LICENSE +0 -0
  45. {hex_zmq_servers-0.3.2.dist-info → hex_zmq_servers-0.3.4.dist-info}/top_level.txt +0 -0
@@ -7,7 +7,8 @@
7
7
  ################################################################
8
8
 
9
9
  import numpy as np
10
- from ...zmq_base import hex_zmq_ts_now
10
+ from collections import deque
11
+ from ...zmq_base import HexRate, hex_zmq_ts_now
11
12
  from ..mujoco_base import HexMujocoClientBase
12
13
 
13
14
  NET_CONFIG = {
@@ -17,6 +18,15 @@ NET_CONFIG = {
17
18
  "server_timeout_ms": 1_000,
18
19
  "server_num_workers": 4,
19
20
  }
21
+ RECV_CONFIG = {
22
+ "head_rgb": True,
23
+ "head_depth": True,
24
+ "left_rgb": True,
25
+ "left_depth": True,
26
+ "right_rgb": True,
27
+ "right_depth": True,
28
+ "obj": True,
29
+ }
20
30
 
21
31
 
22
32
  class HexMujocoE3DesktopClient(HexMujocoClientBase):
@@ -24,8 +34,10 @@ class HexMujocoE3DesktopClient(HexMujocoClientBase):
24
34
  def __init__(
25
35
  self,
26
36
  net_config: dict = NET_CONFIG,
37
+ recv_config: dict = RECV_CONFIG,
27
38
  ):
28
39
  HexMujocoClientBase.__init__(self, net_config)
40
+ self.__recv_config = recv_config
29
41
  self._cmds_seq = {
30
42
  "left": 0,
31
43
  "right": 0,
@@ -38,38 +50,24 @@ class HexMujocoE3DesktopClient(HexMujocoClientBase):
38
50
  "right_rgb": 0,
39
51
  "right_depth": 0,
40
52
  }
41
-
42
- def set_cmds(
43
- self,
44
- cmds: np.ndarray,
45
- robot_name: str | None = None,
46
- ) -> bool:
47
- req_cmd = "set_cmds"
48
- if robot_name is not None:
49
- req_cmd += f"_{robot_name}"
50
- hdr, _ = self.request(
51
- {
52
- "cmd": req_cmd,
53
- "ts": hex_zmq_ts_now(),
54
- "args": self._cmds_seq[robot_name],
55
- },
56
- cmds,
57
- )
58
- # print(f"{req_cmd} seq: {self._cmds_seq[robot_name]}")
59
- try:
60
- cmd = hdr["cmd"]
61
- if cmd == f"{req_cmd}_ok":
62
- self._cmds_seq[robot_name] = (self._cmds_seq[robot_name] +
63
- 1) % self._max_seq_num
64
- return True
65
- else:
66
- return False
67
- except KeyError:
68
- print(f"\033[91m{hdr['cmd']} requires `cmd`\033[0m")
69
- return False
70
- except Exception as e:
71
- print(f"\033[91m{req_cmd} failed: {e}\033[0m")
72
- return False
53
+ self._states_queue = {
54
+ "left": deque(maxlen=10),
55
+ "right": deque(maxlen=10),
56
+ "obj": deque(maxlen=10),
57
+ }
58
+ self._camera_queue = {
59
+ "head_rgb": deque(maxlen=10),
60
+ "head_depth": deque(maxlen=10),
61
+ "left_rgb": deque(maxlen=10),
62
+ "left_depth": deque(maxlen=10),
63
+ "right_rgb": deque(maxlen=10),
64
+ "right_depth": deque(maxlen=10),
65
+ }
66
+ self._cmds_queue = {
67
+ "left": deque(maxlen=10),
68
+ "right": deque(maxlen=10),
69
+ }
70
+ self._wait_for_working()
73
71
 
74
72
  def reset(self):
75
73
  HexMujocoClientBase.reset(self)
@@ -86,6 +84,35 @@ class HexMujocoE3DesktopClient(HexMujocoClientBase):
86
84
  "right_depth": 0,
87
85
  }
88
86
 
87
+ def get_rgb(self, camera_name: str | None = None, newest: bool = False):
88
+ name = f"{camera_name}_rgb"
89
+ try:
90
+ return self._camera_queue[name].popleft(
91
+ ) if not newest else self._camera_queue[name][-1]
92
+ except IndexError:
93
+ return None, None
94
+ except KeyError:
95
+ print(f"\033[91munknown camera name: {name}\033[0m")
96
+ return None, None
97
+
98
+ def get_depth(self, camera_name: str | None = None, newest: bool = False):
99
+ name = f"{camera_name}_depth"
100
+ try:
101
+ return self._camera_queue[name].popleft(
102
+ ) if not newest else self._camera_queue[name][-1]
103
+ except IndexError:
104
+ return None, None
105
+ except KeyError:
106
+ print(f"\033[91munknown camera name: {name}\033[0m")
107
+ return None, None
108
+
109
+ def set_cmds(
110
+ self,
111
+ cmds: np.ndarray,
112
+ robot_name: str | None = None,
113
+ ):
114
+ self._cmds_queue[robot_name].append(cmds)
115
+
89
116
  def _process_frame(
90
117
  self,
91
118
  camera_name: str | None = None,
@@ -116,3 +143,91 @@ class HexMujocoE3DesktopClient(HexMujocoClientBase):
116
143
  except Exception as e:
117
144
  print(f"\033[91m__process_frame failed: {e}\033[0m")
118
145
  return None, None
146
+
147
+ def _set_cmds_inner(
148
+ self,
149
+ cmds: np.ndarray,
150
+ robot_name: str | None = None,
151
+ ) -> bool:
152
+ req_cmd = "set_cmds"
153
+ if robot_name is not None:
154
+ req_cmd += f"_{robot_name}"
155
+ hdr, _ = self.request(
156
+ {
157
+ "cmd": req_cmd,
158
+ "ts": hex_zmq_ts_now(),
159
+ "args": self._cmds_seq[robot_name],
160
+ },
161
+ cmds,
162
+ )
163
+ # print(f"{req_cmd} seq: {self._cmds_seq[robot_name]}")
164
+ try:
165
+ cmd = hdr["cmd"]
166
+ if cmd == f"{req_cmd}_ok":
167
+ self._cmds_seq[robot_name] = (self._cmds_seq[robot_name] +
168
+ 1) % self._max_seq_num
169
+ return True
170
+ else:
171
+ return False
172
+ except KeyError:
173
+ print(f"\033[91m{hdr['cmd']} requires `cmd`\033[0m")
174
+ return False
175
+ except Exception as e:
176
+ print(f"\033[91m{req_cmd} failed: {e}\033[0m")
177
+ return False
178
+
179
+ def _recv_loop(self):
180
+ rate = HexRate(2000)
181
+ image_trig_cnt = 0
182
+ while self._recv_flag:
183
+ hdr, states = self._get_states_inner("left")
184
+ if hdr is not None:
185
+ self._states_queue["left"].append((hdr, states))
186
+ hdr, states = self._get_states_inner("right")
187
+ if hdr is not None:
188
+ self._states_queue["right"].append((hdr, states))
189
+ if self.__recv_config["obj"]:
190
+ hdr, obj_pose = self._get_states_inner("obj")
191
+ if hdr is not None:
192
+ self._states_queue["obj"].append((hdr, obj_pose))
193
+
194
+ image_trig_cnt += 1
195
+ if image_trig_cnt >= 10:
196
+ image_trig_cnt = 0
197
+ if self.__recv_config["head_rgb"]:
198
+ hdr, img = self._get_rgb_inner("head")
199
+ if hdr is not None:
200
+ self._camera_queue["head_rgb"].append((hdr, img))
201
+ if self.__recv_config["head_depth"]:
202
+ hdr, img = self._get_depth_inner("head")
203
+ if hdr is not None:
204
+ self._camera_queue["head_depth"].append((hdr, img))
205
+ if self.__recv_config["left_rgb"]:
206
+ hdr, img = self._get_rgb_inner("left")
207
+ if hdr is not None:
208
+ self._camera_queue["left_rgb"].append((hdr, img))
209
+ if self.__recv_config["left_depth"]:
210
+ hdr, img = self._get_depth_inner("left")
211
+ if hdr is not None:
212
+ self._camera_queue["left_depth"].append((hdr, img))
213
+ if self.__recv_config["right_rgb"]:
214
+ hdr, img = self._get_rgb_inner("right")
215
+ if hdr is not None:
216
+ self._camera_queue["right_rgb"].append((hdr, img))
217
+ if self.__recv_config["right_depth"]:
218
+ hdr, img = self._get_depth_inner("right")
219
+ if hdr is not None:
220
+ self._camera_queue["right_depth"].append((hdr, img))
221
+
222
+ try:
223
+ cmds = self._cmds_queue["left"].popleft()
224
+ _ = self._set_cmds_inner(cmds, "left")
225
+ except IndexError:
226
+ pass
227
+ try:
228
+ cmds = self._cmds_queue["right"].popleft()
229
+ _ = self._set_cmds_inner(cmds, "right")
230
+ except IndexError:
231
+ pass
232
+
233
+ rate.sleep()
@@ -7,7 +7,7 @@
7
7
  ################################################################
8
8
 
9
9
  import numpy as np
10
- from hex_zmq_servers.zmq_base import HexSafeValue
10
+ from collections import deque
11
11
 
12
12
  try:
13
13
  from ..mujoco_base import HexMujocoServerBase
@@ -31,7 +31,7 @@ NET_CONFIG = {
31
31
  }
32
32
 
33
33
  MUJOCO_CONFIG = {
34
- "states_rate": 500,
34
+ "states_rate": 1000,
35
35
  "img_rate": 30,
36
36
  "headless": False,
37
37
  "sens_ts": True,
@@ -53,32 +53,32 @@ class HexMujocoE3DesktopServer(HexMujocoServerBase):
53
53
  # values
54
54
  self._cmds_left_seq = -1
55
55
  self._cmds_right_seq = -1
56
- self._states_left_value = HexSafeValue()
57
- self._states_right_value = HexSafeValue()
58
- self._states_obj_value = HexSafeValue()
59
- self._cmds_left_value = HexSafeValue()
60
- self._cmds_right_value = HexSafeValue()
61
- self._rgb_head_value = HexSafeValue()
62
- self._depth_head_value = HexSafeValue()
63
- self._rgb_left_value = HexSafeValue()
64
- self._depth_left_value = HexSafeValue()
65
- self._rgb_right_value = HexSafeValue()
66
- self._depth_right_value = HexSafeValue()
56
+ self._states_left_queue = deque(maxlen=10)
57
+ self._states_right_queue = deque(maxlen=10)
58
+ self._states_obj_queue = deque(maxlen=10)
59
+ self._cmds_left_queue = deque(maxlen=10)
60
+ self._cmds_right_queue = deque(maxlen=10)
61
+ self._rgb_head_queue = deque(maxlen=10)
62
+ self._depth_head_queue = deque(maxlen=10)
63
+ self._rgb_left_queue = deque(maxlen=10)
64
+ self._depth_left_queue = deque(maxlen=10)
65
+ self._rgb_right_queue = deque(maxlen=10)
66
+ self._depth_right_queue = deque(maxlen=10)
67
67
 
68
68
  def work_loop(self):
69
69
  try:
70
70
  self._device.work_loop([
71
- self._states_left_value,
72
- self._states_right_value,
73
- self._states_obj_value,
74
- self._cmds_left_value,
75
- self._cmds_right_value,
76
- self._rgb_head_value,
77
- self._depth_head_value,
78
- self._rgb_left_value,
79
- self._depth_left_value,
80
- self._rgb_right_value,
81
- self._depth_right_value,
71
+ self._states_left_queue,
72
+ self._states_right_queue,
73
+ self._states_obj_queue,
74
+ self._cmds_left_queue,
75
+ self._cmds_right_queue,
76
+ self._rgb_head_queue,
77
+ self._depth_head_queue,
78
+ self._rgb_left_queue,
79
+ self._depth_left_queue,
80
+ self._rgb_right_queue,
81
+ self._depth_right_queue,
82
82
  self._stop_event,
83
83
  ])
84
84
  finally:
@@ -94,16 +94,18 @@ class HexMujocoE3DesktopServer(HexMujocoServerBase):
94
94
  # get robot name
95
95
  robot_name = recv_hdr["cmd"].split("_")[2]
96
96
  if robot_name == "left":
97
- value = self._states_left_value
97
+ queue = self._states_left_queue
98
98
  elif robot_name == "right":
99
- value = self._states_right_value
99
+ queue = self._states_right_queue
100
100
  elif robot_name == "obj":
101
- value = self._states_obj_value
101
+ queue = self._states_obj_queue
102
102
  else:
103
103
  raise ValueError(f"unknown robot name: {robot_name}")
104
104
 
105
105
  try:
106
- ts, count, states = value.get()
106
+ ts, count, states = queue.popleft()
107
+ except IndexError:
108
+ return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
107
109
  except Exception as e:
108
110
  print(f"\033[91m{recv_hdr['cmd']} failed: {e}\033[0m")
109
111
  return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
@@ -129,10 +131,10 @@ class HexMujocoE3DesktopServer(HexMujocoServerBase):
129
131
  # get robot name
130
132
  robot_name = recv_hdr["cmd"].split("_")[2]
131
133
  if robot_name == "left":
132
- value = self._cmds_left_value
134
+ queue = self._cmds_left_queue
133
135
  cmds_seq = self._cmds_left_seq
134
136
  elif robot_name == "right":
135
- value = self._cmds_right_value
137
+ queue = self._cmds_right_queue
136
138
  cmds_seq = self._cmds_right_seq
137
139
  else:
138
140
  raise ValueError(f"unknown robot name: {robot_name}")
@@ -144,7 +146,7 @@ class HexMujocoE3DesktopServer(HexMujocoServerBase):
144
146
  self._cmds_left_seq = cmds_seq
145
147
  elif robot_name == "right":
146
148
  self._cmds_right_seq = cmds_seq
147
- value.set((recv_hdr["ts"], seq, recv_buf))
149
+ queue.append((recv_hdr["ts"], seq, recv_buf))
148
150
  return self.no_ts_hdr(recv_hdr, True), None
149
151
  else:
150
152
  return self.no_ts_hdr(recv_hdr, False), None
@@ -163,16 +165,18 @@ class HexMujocoE3DesktopServer(HexMujocoServerBase):
163
165
  depth_flag = split_cmd[1] == "depth"
164
166
  camera_name = split_cmd[2]
165
167
  if camera_name == "head":
166
- value = self._rgb_head_value if not depth_flag else self._depth_head_value
168
+ queue = self._rgb_head_queue if not depth_flag else self._depth_head_queue
167
169
  elif camera_name == "left":
168
- value = self._rgb_left_value if not depth_flag else self._depth_left_value
170
+ queue = self._rgb_left_queue if not depth_flag else self._depth_left_queue
169
171
  elif camera_name == "right":
170
- value = self._rgb_right_value if not depth_flag else self._depth_right_value
172
+ queue = self._rgb_right_queue if not depth_flag else self._depth_right_queue
171
173
  else:
172
174
  raise ValueError(f"unknown camera name: {camera_name}")
173
175
 
174
176
  try:
175
- ts, count, img = value.get()
177
+ ts, count, img = queue.popleft()
178
+ except IndexError:
179
+ return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
176
180
  except Exception as e:
177
181
  print(f"\033[91m{recv_hdr['cmd']} failed: {e}\033[0m")
178
182
  return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
@@ -8,12 +8,12 @@
8
8
 
9
9
  import threading
10
10
  import numpy as np
11
+ from collections import deque
11
12
  from abc import abstractmethod
12
13
 
13
14
  from ..device_base import HexDeviceBase
14
15
  from ..zmq_base import (
15
16
  hex_zmq_ts_now,
16
- HexSafeValue,
17
17
  HexZMQClientBase,
18
18
  HexZMQServerBase,
19
19
  )
@@ -88,7 +88,7 @@ class HexMujocoBase(HexDeviceBase):
88
88
  return normed_rads
89
89
 
90
90
  @abstractmethod
91
- def work_loop(self, hex_values: list[HexSafeValue | threading.Event]):
91
+ def work_loop(self, hex_queues: list[deque | threading.Event]):
92
92
  raise NotImplementedError(
93
93
  "`work_loop` should be implemented by the child class")
94
94
 
@@ -107,6 +107,13 @@ class HexMujocoClientBase(HexZMQClientBase):
107
107
  self._cmds_seq = 0
108
108
  self._rgb_seq = 0
109
109
  self._depth_seq = 0
110
+ self._states_queue = {
111
+ "robot": deque(maxlen=10),
112
+ "obj": deque(maxlen=10),
113
+ }
114
+ self._rgb_queue = deque(maxlen=10)
115
+ self._depth_queue = deque(maxlen=10)
116
+ self._cmds_queue = deque(maxlen=10)
110
117
 
111
118
  def __del__(self):
112
119
  HexZMQClientBase.__del__(self)
@@ -133,7 +140,77 @@ class HexMujocoClientBase(HexZMQClientBase):
133
140
  _, limits = self.request({"cmd": "get_limits"})
134
141
  return limits
135
142
 
136
- def get_states(self, robot_name: str | None = None):
143
+ def get_states(self, robot_name: str | None = None, newest: bool = False):
144
+ try:
145
+ return self._states_queue[robot_name].popleft(
146
+ ) if not newest else self._states_queue[robot_name][-1]
147
+ except IndexError:
148
+ return None, None
149
+ except KeyError:
150
+ print(f"\033[91munknown robot name: {robot_name}\033[0m")
151
+ return None, None
152
+
153
+ def get_rgb(self, camera_name: str | None = None, newest: bool = False):
154
+ try:
155
+ return self._rgb_queue.popleft(
156
+ ) if not newest else self._rgb_queue[-1]
157
+ except IndexError:
158
+ return None, None
159
+
160
+ def get_depth(self, camera_name: str | None = None, newest: bool = False):
161
+ try:
162
+ return self._depth_queue.popleft(
163
+ ) if not newest else self._depth_queue[-1]
164
+ except IndexError:
165
+ return None, None
166
+
167
+ def set_cmds(self, cmds: np.ndarray):
168
+ self._cmds_queue.append(cmds)
169
+
170
+ def get_intri(self):
171
+ intri_hdr, intri = self.request({"cmd": "get_intri"})
172
+ return intri_hdr, intri
173
+
174
+ def _get_rgb_inner(self, camera_name: str | None = None):
175
+ return self._process_frame(camera_name, False)
176
+
177
+ def _get_depth_inner(self, camera_name: str | None = None):
178
+ return self._process_frame(camera_name, True)
179
+
180
+ def _process_frame(
181
+ self,
182
+ camera_name: str | None = None,
183
+ depth_flag: bool = False,
184
+ ):
185
+ req_cmd = f"get_{'depth' if depth_flag else 'rgb'}"
186
+ if camera_name is not None:
187
+ req_cmd += f"_{camera_name}"
188
+
189
+ hdr, img = self.request({
190
+ "cmd":
191
+ req_cmd,
192
+ "args": (1 + (self._depth_seq if depth_flag else self._rgb_seq)) %
193
+ self._max_seq_num,
194
+ })
195
+
196
+ try:
197
+ cmd = hdr["cmd"]
198
+ if cmd == f"{req_cmd}_ok":
199
+ if depth_flag:
200
+ self._depth_seq = hdr["args"]
201
+ else:
202
+ self._rgb_seq = hdr["args"]
203
+ return hdr, img
204
+ else:
205
+ return None, None
206
+ except KeyError:
207
+ print(f"\033[91m{hdr['cmd']} requires `cmd`\033[0m")
208
+ return None, None
209
+ except Exception as e:
210
+ print(f"\033[91m__process_frame failed: {e}\033[0m")
211
+ return None, None
212
+
213
+ def _get_states_inner(self, robot_name: str | None = None):
137
214
  req_cmd = "get_states"
138
215
  if robot_name is not None:
139
216
  req_cmd += f"_{robot_name}"
@@ -156,7 +233,7 @@ class HexMujocoClientBase(HexZMQClientBase):
156
233
  print(f"\033[91m{req_cmd} failed: {e}\033[0m")
157
234
  return None, None
158
235
 
159
- def set_cmds(
236
+ def _set_cmds_inner(
160
237
  self,
161
238
  cmds: np.ndarray,
162
239
  ) -> bool:
@@ -184,71 +261,28 @@ class HexMujocoClientBase(HexZMQClientBase):
184
261
  print(f"\033[91m{req_cmd} failed: {e}\033[0m")
185
262
  return False
186
263
 
187
- def get_intri(self):
188
- intri_hdr, intri = self.request({"cmd": "get_intri"})
189
- return intri_hdr, intri
190
-
191
- def get_rgb(self, camera_name: str | None = None):
192
- return self._process_frame(camera_name, False)
193
-
194
- def get_depth(self, camera_name: str | None = None):
195
- return self._process_frame(camera_name, True)
196
-
197
- def _process_frame(
198
- self,
199
- camera_name: str | None = None,
200
- depth_flag: bool = False,
201
- ):
202
- req_cmd = f"get_{'depth' if depth_flag else 'rgb'}"
203
- if camera_name is not None:
204
- req_cmd += f"_{camera_name}"
205
-
206
- hdr, img = self.request({
207
- "cmd":
208
- req_cmd,
209
- "args": (1 + (self._depth_seq if depth_flag else self._rgb_seq)) %
210
- self._max_seq_num,
211
- })
212
-
213
- try:
214
- cmd = hdr["cmd"]
215
- if cmd == f"{req_cmd}_ok":
216
- if depth_flag:
217
- self._depth_seq = hdr["args"]
218
- else:
219
- self._rgb_seq = hdr["args"]
220
- return hdr, img
221
- else:
222
- return None, None
223
- except KeyError:
224
- print(f"\033[91m{hdr['cmd']} requires `cmd`\033[0m")
225
- return None, None
226
- except Exception as e:
227
- print(f"\033[91m__process_frame failed: {e}\033[0m")
228
- return None, None
229
-
230
264
 
231
265
  class HexMujocoServerBase(HexZMQServerBase):
232
266
 
233
267
  def __init__(self, net_config: dict = NET_CONFIG):
234
268
  HexZMQServerBase.__init__(self, net_config)
235
269
  self._device: HexDeviceBase = None
236
- self._states_value = HexSafeValue()
237
- self._obj_pose_value = HexSafeValue()
238
- self._cmds_value = HexSafeValue()
270
+ self._states_queue = deque(maxlen=10)
271
+ self._obj_pose_queue = deque(maxlen=10)
272
+ self._cmds_queue = deque(maxlen=10)
239
273
  self._cmds_seq = -1
240
- self._rgb_value = HexSafeValue()
241
- self._depth_value = HexSafeValue()
274
+ self._rgb_queue = deque(maxlen=10)
275
+ self._depth_queue = deque(maxlen=10)
242
276
  self._seq_clear_flag = False
243
277
 
244
278
  def work_loop(self):
245
279
  try:
246
280
  self._device.work_loop([
247
- self._states_value,
248
- self._obj_pose_value,
249
- self._cmds_value,
250
- self._rgb_value,
251
- self._depth_value,
281
+ self._states_queue,
282
+ self._obj_pose_queue,
283
+ self._cmds_queue,
284
+ self._rgb_queue,
285
+ self._depth_queue,
252
286
  self._stop_event,
253
287
  ])
254
288
  finally:
@@ -266,7 +300,9 @@ class HexMujocoServerBase(HexZMQServerBase):
266
300
  return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
267
301
 
268
302
  try:
269
- ts, count, states = self._states_value.get()
303
+ ts, count, states = self._states_queue.popleft()
304
+ except IndexError:
305
+ return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
270
306
  except Exception as e:
271
307
  print(f"\033[91m{recv_hdr['cmd']} failed: {e}\033[0m")
272
308
  return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
@@ -292,7 +328,7 @@ class HexMujocoServerBase(HexZMQServerBase):
292
328
  delta = (seq - self._cmds_seq) % self._max_seq_num
293
329
  if delta >= 0 and delta < 1e6:
294
330
  self._cmds_seq = seq
295
- self._cmds_value.set((recv_hdr["ts"], seq, recv_buf))
331
+ self._cmds_queue.append((recv_hdr["ts"], seq, recv_buf))
296
332
  return self.no_ts_hdr(recv_hdr, True), None
297
333
  else:
298
334
  return self.no_ts_hdr(recv_hdr, False), None
@@ -309,13 +345,14 @@ class HexMujocoServerBase(HexZMQServerBase):
309
345
  # get camera config
310
346
  split_cmd = recv_hdr["cmd"].split("_")
311
347
  depth_flag = split_cmd[1] == "depth"
312
- if depth_flag:
313
- value = self._depth_value
314
- else:
315
- value = self._rgb_value
316
348
 
317
349
  try:
318
- ts, count, img = value.get()
350
+ if depth_flag:
351
+ ts, count, img = self._depth_queue.popleft()
352
+ else:
353
+ ts, count, img = self._rgb_queue.popleft()
354
+ except IndexError:
355
+ return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
319
356
  except Exception as e:
320
357
  print(f"\033[91m{recv_hdr['cmd']} failed: {e}\033[0m")
321
358
  return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
@@ -8,13 +8,13 @@
8
8
 
9
9
  import threading
10
10
  import numpy as np
11
+ from collections import deque
11
12
 
12
13
  from ..robot_base import HexRobotBase
13
14
  from ...zmq_base import (
14
15
  hex_zmq_ts_now,
15
16
  hex_zmq_ts_delta_ms,
16
17
  HexRate,
17
- HexSafeValue,
18
18
  )
19
19
  from ...hex_launch import hex_log, HEX_LOG_LEVEL
20
20
 
@@ -47,10 +47,10 @@ class HexRobotDummy(HexRobotBase):
47
47
  def __del__(self):
48
48
  HexRobotBase.__del__(self)
49
49
 
50
- def work_loop(self, hex_values: list[HexSafeValue | threading.Event]):
51
- states_value = hex_values[0]
52
- cmds_value = hex_values[1]
53
- stop_event = hex_values[2]
50
+ def work_loop(self, hex_queues: list[deque | threading.Event]):
51
+ states_queue = hex_queues[0]
52
+ cmds_queue = hex_queues[1]
53
+ stop_event = hex_queues[2]
54
54
 
55
55
  dummy_states = np.zeros((self._dofs[0], 3))
56
56
  states_count = 0
@@ -58,11 +58,15 @@ class HexRobotDummy(HexRobotBase):
58
58
  rate = HexRate(1000)
59
59
  while self._working.is_set() and not stop_event.is_set():
60
60
  # states
61
- states_value.set((hex_zmq_ts_now(), states_count, dummy_states))
61
+ states_queue.append((hex_zmq_ts_now(), states_count, dummy_states))
62
62
  states_count = (states_count + 1) % self._max_seq_num
63
63
 
64
64
  # cmds
65
- cmds_pack = cmds_value.get(timeout_s=-1.0)
65
+ cmds_pack = None
66
+ try:
67
+ cmds_pack = cmds_queue.popleft()
68
+ except IndexError:
69
+ pass
66
70
  if cmds_pack is not None:
67
71
  ts, seq, cmds = cmds_pack
68
72
  if seq != last_cmds_seq:
@@ -24,3 +24,4 @@ class HexRobotDummyClient(HexRobotClientBase):
24
24
  net_config: dict = NET_CONFIG,
25
25
  ):
26
26
  HexRobotClientBase.__init__(self, net_config)
27
+ self._wait_for_working()