hex-zmq-servers 0.3.3__py3-none-any.whl → 0.3.5__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 +5 -3
- 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/cam_realsense.py +9 -9
- hex_zmq_servers/cam/realsense/cam_realsense_cli.py +1 -0
- hex_zmq_servers/cam/rgb/cam_rgb.py +33 -7
- hex_zmq_servers/cam/rgb/cam_rgb_cli.py +11 -0
- hex_zmq_servers/config/cam_rgb.json +8 -0
- hex_zmq_servers/config/mujoco_archer_y6.json +1 -1
- hex_zmq_servers/config/mujoco_e3_desktop.json +1 -1
- hex_zmq_servers/config/robot_hexarm.json +1 -1
- hex_zmq_servers/device_base.py +3 -2
- hex_zmq_servers/hex_launch.py +8 -3
- hex_zmq_servers/mujoco/archer_y6/model/scene.xml +1 -1
- hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6.py +28 -22
- 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/scene.xml +1 -1
- hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop.py +50 -40
- 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 -23
- 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 +92 -31
- {hex_zmq_servers-0.3.3.dist-info → hex_zmq_servers-0.3.5.dist-info}/METADATA +1 -1
- {hex_zmq_servers-0.3.3.dist-info → hex_zmq_servers-0.3.5.dist-info}/RECORD +38 -38
- {hex_zmq_servers-0.3.3.dist-info → hex_zmq_servers-0.3.5.dist-info}/WHEEL +0 -0
- {hex_zmq_servers-0.3.3.dist-info → hex_zmq_servers-0.3.5.dist-info}/licenses/LICENSE +0 -0
- {hex_zmq_servers-0.3.3.dist-info → hex_zmq_servers-0.3.5.dist-info}/top_level.txt +0 -0
|
@@ -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:
|
|
@@ -11,13 +11,13 @@ import subprocess
|
|
|
11
11
|
import time
|
|
12
12
|
import threading
|
|
13
13
|
import numpy as np
|
|
14
|
+
from collections import deque
|
|
14
15
|
|
|
15
16
|
from ..robot_base import HexRobotBase
|
|
16
17
|
from ...zmq_base import (
|
|
17
18
|
hex_zmq_ts_now,
|
|
18
19
|
hex_zmq_ts_delta_ms,
|
|
19
20
|
HexRate,
|
|
20
|
-
HexSafeValue,
|
|
21
21
|
)
|
|
22
22
|
from ...hex_launch import hex_log, HEX_LOG_LEVEL
|
|
23
23
|
from dynamixel_sdk.group_sync_read import GroupSyncRead
|
|
@@ -104,10 +104,10 @@ class HexRobotGello(HexRobotBase):
|
|
|
104
104
|
# start work loop
|
|
105
105
|
self._working.set()
|
|
106
106
|
|
|
107
|
-
def work_loop(self,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
stop_event =
|
|
107
|
+
def work_loop(self, hex_queues: list[deque | threading.Event]):
|
|
108
|
+
states_queue = hex_queues[0]
|
|
109
|
+
cmds_queue = hex_queues[1]
|
|
110
|
+
stop_event = hex_queues[2]
|
|
111
111
|
|
|
112
112
|
states_count = 0
|
|
113
113
|
last_cmds_seq = -1
|
|
@@ -116,11 +116,15 @@ class HexRobotGello(HexRobotBase):
|
|
|
116
116
|
# states
|
|
117
117
|
ts, states = self.__get_states()
|
|
118
118
|
if states is not None:
|
|
119
|
-
|
|
119
|
+
states_queue.append((ts, states_count, states))
|
|
120
120
|
states_count = (states_count + 1) % self._max_seq_num
|
|
121
121
|
|
|
122
122
|
# cmds
|
|
123
|
-
cmds_pack =
|
|
123
|
+
cmds_pack = None
|
|
124
|
+
try:
|
|
125
|
+
cmds_pack = cmds_queue.popleft()
|
|
126
|
+
except IndexError:
|
|
127
|
+
pass
|
|
124
128
|
if cmds_pack is not None:
|
|
125
129
|
ts, seq, cmds = cmds_pack
|
|
126
130
|
if seq != last_cmds_seq:
|
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
import time
|
|
10
10
|
import threading
|
|
11
11
|
import numpy as np
|
|
12
|
+
from collections import deque
|
|
12
13
|
|
|
13
14
|
from ..robot_base import HexRobotBase
|
|
14
15
|
from ...zmq_base import (
|
|
15
16
|
hex_zmq_ts_now,
|
|
16
17
|
hex_zmq_ts_delta_ms,
|
|
17
18
|
HexRate,
|
|
18
|
-
HexSafeValue,
|
|
19
19
|
)
|
|
20
20
|
from ...hex_launch import hex_log, HEX_LOG_LEVEL
|
|
21
21
|
from hex_device import HexDeviceApi, MotorBase
|
|
@@ -73,6 +73,10 @@ class HexRobotHexarm(HexRobotBase):
|
|
|
73
73
|
self.__arm_archer: MotorBase | None = None
|
|
74
74
|
self.__gripper: MotorBase | None = None
|
|
75
75
|
|
|
76
|
+
# buffer
|
|
77
|
+
self.__arm_state_buffer: dict | None = None
|
|
78
|
+
self.__gripper_state_buffer: dict | None = None
|
|
79
|
+
|
|
76
80
|
# open device
|
|
77
81
|
self.__hex_api = HexDeviceApi(
|
|
78
82
|
ws_url=f"ws://{device_ip}:{device_port}",
|
|
@@ -122,26 +126,30 @@ class HexRobotHexarm(HexRobotBase):
|
|
|
122
126
|
# start work loop
|
|
123
127
|
self._working.set()
|
|
124
128
|
|
|
125
|
-
def work_loop(self,
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
stop_event =
|
|
129
|
+
def work_loop(self, hex_queues: list[deque | threading.Event]):
|
|
130
|
+
states_queue = hex_queues[0]
|
|
131
|
+
cmds_queue = hex_queues[1]
|
|
132
|
+
stop_event = hex_queues[2]
|
|
129
133
|
|
|
130
134
|
last_states_ts = hex_zmq_ts_now()
|
|
131
135
|
states_count = 0
|
|
132
136
|
last_cmds_seq = -1
|
|
133
|
-
rate = HexRate(
|
|
137
|
+
rate = HexRate(2000)
|
|
134
138
|
while self._working.is_set() and not stop_event.is_set():
|
|
135
139
|
# states
|
|
136
140
|
ts, states = self.__get_states()
|
|
137
141
|
if states is not None:
|
|
138
|
-
if hex_zmq_ts_delta_ms(ts, last_states_ts) >
|
|
142
|
+
if hex_zmq_ts_delta_ms(ts, last_states_ts) > 1e-6:
|
|
139
143
|
last_states_ts = ts
|
|
140
|
-
|
|
144
|
+
states_queue.append((ts, states_count, states))
|
|
141
145
|
states_count = (states_count + 1) % self._max_seq_num
|
|
142
146
|
|
|
143
147
|
# cmds
|
|
144
|
-
cmds_pack =
|
|
148
|
+
cmds_pack = None
|
|
149
|
+
try:
|
|
150
|
+
cmds_pack = cmds_queue.popleft()
|
|
151
|
+
except IndexError:
|
|
152
|
+
pass
|
|
145
153
|
if cmds_pack is not None:
|
|
146
154
|
ts, seq, cmds = cmds_pack
|
|
147
155
|
if seq != last_cmds_seq:
|
|
@@ -160,22 +168,47 @@ class HexRobotHexarm(HexRobotBase):
|
|
|
160
168
|
return None, None
|
|
161
169
|
|
|
162
170
|
# (arm_dofs, 3) # pos vel eff
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
eff = arm_states_dict['eff']
|
|
167
|
-
ts = arm_states_dict['ts']
|
|
171
|
+
if self.__arm_state_buffer is None:
|
|
172
|
+
self.__arm_state_buffer = self.__arm_archer.get_simple_motor_status(
|
|
173
|
+
)
|
|
168
174
|
|
|
169
175
|
# (gripper_dofs, 3) # pos vel eff
|
|
170
|
-
if self.__gripper is not None:
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
176
|
+
if self.__gripper is not None and self.__gripper_state_buffer is None:
|
|
177
|
+
self.__gripper_state_buffer = self.__gripper.get_simple_motor_status(
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
arm_ready = self.__arm_state_buffer is not None
|
|
181
|
+
gripper_ready = self.__gripper is None or self.__gripper_state_buffer is not None
|
|
182
|
+
if arm_ready and gripper_ready:
|
|
183
|
+
arm_ts = self.__arm_state_buffer['ts']
|
|
184
|
+
gripper_ts = self.__gripper_state_buffer[
|
|
185
|
+
'ts'] if self.__gripper is not None else arm_ts
|
|
186
|
+
|
|
187
|
+
delta_ms = hex_zmq_ts_delta_ms(arm_ts, gripper_ts)
|
|
188
|
+
if np.fabs(delta_ms) < 1e-6:
|
|
189
|
+
pos = self.__arm_state_buffer['pos']
|
|
190
|
+
vel = self.__arm_state_buffer['vel']
|
|
191
|
+
eff = self.__arm_state_buffer['eff']
|
|
192
|
+
|
|
193
|
+
if self.__gripper is not None:
|
|
194
|
+
pos = np.concatenate(
|
|
195
|
+
[pos, self.__gripper_state_buffer['pos']])
|
|
196
|
+
vel = np.concatenate(
|
|
197
|
+
[vel, self.__gripper_state_buffer['vel']])
|
|
198
|
+
eff = np.concatenate(
|
|
199
|
+
[eff, self.__gripper_state_buffer['eff']])
|
|
200
|
+
|
|
201
|
+
state = np.array([pos, vel, eff]).T
|
|
202
|
+
self.__arm_state_buffer, self.__gripper_state_buffer = None, None
|
|
203
|
+
return arm_ts if self.__sens_ts else hex_zmq_ts_now(), state
|
|
204
|
+
elif delta_ms > 0.0:
|
|
205
|
+
self.__gripper_state_buffer = None
|
|
206
|
+
return None, None
|
|
207
|
+
else:
|
|
208
|
+
self.__arm_state_buffer = None
|
|
209
|
+
return None, None
|
|
210
|
+
|
|
211
|
+
return None, None
|
|
179
212
|
|
|
180
213
|
def __set_cmds(self, cmds: np.ndarray) -> bool:
|
|
181
214
|
# cmds: (n)
|