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.
- hex_zmq_servers/__init__.py +45 -20
- hex_zmq_servers/cam/__init__.py +29 -5
- hex_zmq_servers/cam/berxel/cam_berxel.py +8 -10
- hex_zmq_servers/cam/berxel/cam_berxel_cli.py +1 -0
- hex_zmq_servers/cam/cam_base.py +40 -10
- hex_zmq_servers/cam/dummy/cam_dummy.py +7 -7
- hex_zmq_servers/cam/dummy/cam_dummy_cli.py +1 -0
- hex_zmq_servers/cam/realsense/__init__.py +17 -0
- hex_zmq_servers/cam/realsense/cam_realsense.py +157 -0
- hex_zmq_servers/cam/realsense/cam_realsense_cli.py +31 -0
- hex_zmq_servers/cam/realsense/cam_realsense_srv.py +75 -0
- hex_zmq_servers/cam/rgb/__init__.py +17 -0
- hex_zmq_servers/cam/rgb/cam_rgb.py +133 -0
- hex_zmq_servers/cam/rgb/cam_rgb_cli.py +41 -0
- hex_zmq_servers/cam/rgb/cam_rgb_srv.py +75 -0
- hex_zmq_servers/config/cam_realsense.json +15 -0
- hex_zmq_servers/config/cam_rgb.json +26 -0
- hex_zmq_servers/config/mujoco_archer_y6.json +2 -1
- hex_zmq_servers/config/mujoco_e3_desktop.json +6 -1
- hex_zmq_servers/config/robot_hexarm.json +1 -1
- hex_zmq_servers/device_base.py +3 -2
- hex_zmq_servers/mujoco/archer_y6/model/robot.xml +6 -6
- hex_zmq_servers/mujoco/archer_y6/model/scene.xml +1 -1
- hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6.py +74 -39
- hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6_cli.py +42 -0
- hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6_srv.py +16 -14
- hex_zmq_servers/mujoco/e3_desktop/model/robot.xml +12 -12
- hex_zmq_servers/mujoco/e3_desktop/model/scene.xml +1 -1
- hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop.py +138 -70
- hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop_cli.py +148 -33
- hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop_srv.py +39 -35
- hex_zmq_servers/mujoco/mujoco_base.py +101 -64
- hex_zmq_servers/robot/dummy/robot_dummy.py +11 -7
- hex_zmq_servers/robot/dummy/robot_dummy_cli.py +1 -0
- hex_zmq_servers/robot/gello/robot_gello.py +11 -7
- hex_zmq_servers/robot/gello/robot_gello_cli.py +1 -0
- hex_zmq_servers/robot/hexarm/robot_hexarm.py +56 -22
- hex_zmq_servers/robot/hexarm/robot_hexarm_cli.py +1 -0
- hex_zmq_servers/robot/robot_base.py +40 -10
- hex_zmq_servers/zmq_base.py +97 -33
- {hex_zmq_servers-0.3.2.dist-info → hex_zmq_servers-0.3.4.dist-info}/METADATA +7 -6
- {hex_zmq_servers-0.3.2.dist-info → hex_zmq_servers-0.3.4.dist-info}/RECORD +45 -35
- {hex_zmq_servers-0.3.2.dist-info → hex_zmq_servers-0.3.4.dist-info}/WHEEL +0 -0
- {hex_zmq_servers-0.3.2.dist-info → hex_zmq_servers-0.3.4.dist-info}/licenses/LICENSE +0 -0
- {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
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
|
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":
|
|
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.
|
|
57
|
-
self.
|
|
58
|
-
self.
|
|
59
|
-
self.
|
|
60
|
-
self.
|
|
61
|
-
self.
|
|
62
|
-
self.
|
|
63
|
-
self.
|
|
64
|
-
self.
|
|
65
|
-
self.
|
|
66
|
-
self.
|
|
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.
|
|
72
|
-
self.
|
|
73
|
-
self.
|
|
74
|
-
self.
|
|
75
|
-
self.
|
|
76
|
-
self.
|
|
77
|
-
self.
|
|
78
|
-
self.
|
|
79
|
-
self.
|
|
80
|
-
self.
|
|
81
|
-
self.
|
|
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
|
-
|
|
97
|
+
queue = self._states_left_queue
|
|
98
98
|
elif robot_name == "right":
|
|
99
|
-
|
|
99
|
+
queue = self._states_right_queue
|
|
100
100
|
elif robot_name == "obj":
|
|
101
|
-
|
|
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 =
|
|
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
|
-
|
|
134
|
+
queue = self._cmds_left_queue
|
|
133
135
|
cmds_seq = self._cmds_left_seq
|
|
134
136
|
elif robot_name == "right":
|
|
135
|
-
|
|
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
|
-
|
|
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
|
-
|
|
168
|
+
queue = self._rgb_head_queue if not depth_flag else self._depth_head_queue
|
|
167
169
|
elif camera_name == "left":
|
|
168
|
-
|
|
170
|
+
queue = self._rgb_left_queue if not depth_flag else self._depth_left_queue
|
|
169
171
|
elif camera_name == "right":
|
|
170
|
-
|
|
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 =
|
|
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,
|
|
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
|
|
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.
|
|
237
|
-
self.
|
|
238
|
-
self.
|
|
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.
|
|
241
|
-
self.
|
|
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.
|
|
248
|
-
self.
|
|
249
|
-
self.
|
|
250
|
-
self.
|
|
251
|
-
self.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
stop_event =
|
|
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
|
-
|
|
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 =
|
|
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:
|