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
|
@@ -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
|
-
|
|
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
|
|
175
210
|
|
|
176
|
-
|
|
177
|
-
return ts if self.__sens_ts else hex_zmq_ts_now(), np.array(
|
|
178
|
-
[pos, vel, eff]).T
|
|
211
|
+
return None, None
|
|
179
212
|
|
|
180
213
|
def __set_cmds(self, cmds: np.ndarray) -> bool:
|
|
181
214
|
# cmds: (n)
|
|
@@ -254,5 +287,6 @@ class HexRobotHexarm(HexRobotBase):
|
|
|
254
287
|
return
|
|
255
288
|
self._working.clear()
|
|
256
289
|
self.__arm_archer.stop()
|
|
290
|
+
time.sleep(0.5)
|
|
257
291
|
self.__hex_api.close()
|
|
258
292
|
hex_log(HEX_LOG_LEVEL["info"], "HexRobotHexarm closed")
|
|
@@ -8,12 +8,13 @@
|
|
|
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
|
-
|
|
17
|
+
HexRate,
|
|
17
18
|
HexZMQClientBase,
|
|
18
19
|
HexZMQServerBase,
|
|
19
20
|
)
|
|
@@ -82,7 +83,7 @@ class HexRobotBase(HexDeviceBase):
|
|
|
82
83
|
return normed_rads
|
|
83
84
|
|
|
84
85
|
@abstractmethod
|
|
85
|
-
def work_loop(self,
|
|
86
|
+
def work_loop(self, hex_queues: list[deque | threading.Event]):
|
|
86
87
|
raise NotImplementedError(
|
|
87
88
|
"`work_loop` should be implemented by the child class")
|
|
88
89
|
|
|
@@ -98,6 +99,8 @@ class HexRobotClientBase(HexZMQClientBase):
|
|
|
98
99
|
HexZMQClientBase.__init__(self, net_config)
|
|
99
100
|
self._states_seq = 0
|
|
100
101
|
self._cmds_seq = 0
|
|
102
|
+
self._states_queue = deque(maxlen=10)
|
|
103
|
+
self._cmds_queue = deque(maxlen=10)
|
|
101
104
|
|
|
102
105
|
def __del__(self):
|
|
103
106
|
HexZMQClientBase.__del__(self)
|
|
@@ -114,7 +117,17 @@ class HexRobotClientBase(HexZMQClientBase):
|
|
|
114
117
|
_, limits = self.request({"cmd": "get_limits"})
|
|
115
118
|
return limits
|
|
116
119
|
|
|
117
|
-
def get_states(self):
|
|
120
|
+
def get_states(self, newest: bool = False):
|
|
121
|
+
try:
|
|
122
|
+
return self._states_queue.popleft(
|
|
123
|
+
) if not newest else self._states_queue[-1]
|
|
124
|
+
except IndexError:
|
|
125
|
+
return None, None
|
|
126
|
+
|
|
127
|
+
def set_cmds(self, cmds: np.ndarray):
|
|
128
|
+
self._cmds_queue.append(cmds)
|
|
129
|
+
|
|
130
|
+
def _get_states_inner(self):
|
|
118
131
|
hdr, states = self.request({
|
|
119
132
|
"cmd":
|
|
120
133
|
"get_states",
|
|
@@ -134,7 +147,7 @@ class HexRobotClientBase(HexZMQClientBase):
|
|
|
134
147
|
print(f"\033[91mget_states failed: {e}\033[0m")
|
|
135
148
|
return None, None
|
|
136
149
|
|
|
137
|
-
def
|
|
150
|
+
def _set_cmds_inner(self, cmds: np.ndarray) -> bool:
|
|
138
151
|
hdr, _ = self.request(
|
|
139
152
|
{
|
|
140
153
|
"cmd": "set_cmds",
|
|
@@ -158,14 +171,29 @@ class HexRobotClientBase(HexZMQClientBase):
|
|
|
158
171
|
print(f"\033[91mset_cmds failed: {e}\033[0m")
|
|
159
172
|
return False
|
|
160
173
|
|
|
174
|
+
def _recv_loop(self):
|
|
175
|
+
rate = HexRate(2000)
|
|
176
|
+
while self._recv_flag:
|
|
177
|
+
hdr, states = self._get_states_inner()
|
|
178
|
+
if hdr is not None:
|
|
179
|
+
self._states_queue.append((hdr, states))
|
|
180
|
+
|
|
181
|
+
try:
|
|
182
|
+
cmds = self._cmds_queue.popleft()
|
|
183
|
+
_ = self._set_cmds_inner(cmds)
|
|
184
|
+
except IndexError:
|
|
185
|
+
pass
|
|
186
|
+
|
|
187
|
+
rate.sleep()
|
|
188
|
+
|
|
161
189
|
|
|
162
190
|
class HexRobotServerBase(HexZMQServerBase):
|
|
163
191
|
|
|
164
192
|
def __init__(self, net_config: dict = NET_CONFIG):
|
|
165
193
|
HexZMQServerBase.__init__(self, net_config)
|
|
166
194
|
self._device: HexDeviceBase = None
|
|
167
|
-
self.
|
|
168
|
-
self.
|
|
195
|
+
self._states_queue = deque(maxlen=10)
|
|
196
|
+
self._cmds_queue = deque(maxlen=10)
|
|
169
197
|
self._cmds_seq = -1
|
|
170
198
|
self._seq_clear_flag = False
|
|
171
199
|
|
|
@@ -176,8 +204,8 @@ class HexRobotServerBase(HexZMQServerBase):
|
|
|
176
204
|
def work_loop(self):
|
|
177
205
|
try:
|
|
178
206
|
self._device.work_loop([
|
|
179
|
-
self.
|
|
180
|
-
self.
|
|
207
|
+
self._states_queue,
|
|
208
|
+
self._cmds_queue,
|
|
181
209
|
self._stop_event,
|
|
182
210
|
])
|
|
183
211
|
finally:
|
|
@@ -195,7 +223,9 @@ class HexRobotServerBase(HexZMQServerBase):
|
|
|
195
223
|
return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
|
|
196
224
|
|
|
197
225
|
try:
|
|
198
|
-
ts, count, states = self.
|
|
226
|
+
ts, count, states = self._states_queue.popleft()
|
|
227
|
+
except IndexError:
|
|
228
|
+
return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
|
|
199
229
|
except Exception as e:
|
|
200
230
|
print(f"\033[91m{recv_hdr['cmd']} failed: {e}\033[0m")
|
|
201
231
|
return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
|
|
@@ -221,7 +251,7 @@ class HexRobotServerBase(HexZMQServerBase):
|
|
|
221
251
|
delta = (seq - self._cmds_seq) % self._max_seq_num
|
|
222
252
|
if delta >= 0 and delta < 1e6:
|
|
223
253
|
self._cmds_seq = seq
|
|
224
|
-
self.
|
|
254
|
+
self._cmds_queue.append((recv_hdr["ts"], seq, recv_buf))
|
|
225
255
|
return self.no_ts_hdr(recv_hdr, True), None
|
|
226
256
|
else:
|
|
227
257
|
return self.no_ts_hdr(recv_hdr, False), None
|
hex_zmq_servers/zmq_base.py
CHANGED
|
@@ -6,11 +6,10 @@
|
|
|
6
6
|
# Date : 2025-09-12
|
|
7
7
|
################################################################
|
|
8
8
|
|
|
9
|
-
import os, signal
|
|
10
|
-
import time
|
|
11
|
-
import zmq
|
|
9
|
+
import os, signal, json
|
|
10
|
+
import time, ctypes, ctypes.util
|
|
12
11
|
import threading
|
|
13
|
-
import
|
|
12
|
+
import zmq
|
|
14
13
|
import numpy as np
|
|
15
14
|
from abc import ABC, abstractmethod
|
|
16
15
|
|
|
@@ -21,14 +20,73 @@ MAX_SEQ_NUM = int(1e12)
|
|
|
21
20
|
################################################################
|
|
22
21
|
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
class SingletonMeta(type):
|
|
24
|
+
_instances = {}
|
|
25
|
+
|
|
26
|
+
def __call__(cls, *args, **kwargs):
|
|
27
|
+
if cls not in cls._instances:
|
|
28
|
+
cls._instances[cls] = super().__call__(*args, **kwargs)
|
|
29
|
+
return cls._instances[cls]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class HexTimeManager(metaclass=SingletonMeta):
|
|
33
|
+
|
|
34
|
+
class timespec(ctypes.Structure):
|
|
35
|
+
_fields_ = [("tv_sec", ctypes.c_long), ("tv_nsec", ctypes.c_long)]
|
|
36
|
+
|
|
37
|
+
def __init__(self):
|
|
38
|
+
self.__use_ptp = False
|
|
39
|
+
ptp_path = os.getenv("HEX_PTP_CLOCK", None)
|
|
40
|
+
if ptp_path is not None:
|
|
41
|
+
self.__fd = os.open(ptp_path, os.O_RDONLY | os.O_CLOEXEC)
|
|
42
|
+
self.__clock_id = ((~self.__fd) << 3) | 3
|
|
43
|
+
self.__libc = ctypes.CDLL(
|
|
44
|
+
ctypes.util.find_library("c"),
|
|
45
|
+
use_errno=True,
|
|
46
|
+
)
|
|
47
|
+
self.__use_ptp = True
|
|
48
|
+
print(f"Using PTP clock from {ptp_path}")
|
|
49
|
+
else:
|
|
50
|
+
print("Using system clock")
|
|
51
|
+
|
|
52
|
+
def __del__(self):
|
|
53
|
+
if self.__use_ptp:
|
|
54
|
+
os.close(self.__fd)
|
|
55
|
+
|
|
56
|
+
def get_now_ns(self) -> int:
|
|
57
|
+
if self.__use_ptp:
|
|
58
|
+
ts = self.timespec()
|
|
59
|
+
if self.__libc.clock_gettime(self.__clock_id,
|
|
60
|
+
ctypes.byref(ts)) != 0:
|
|
61
|
+
err = ctypes.get_errno()
|
|
62
|
+
raise OSError(err, os.strerror(err))
|
|
63
|
+
return ts.tv_sec * 1_000_000_000 + ts.tv_nsec
|
|
64
|
+
else:
|
|
65
|
+
return time.perf_counter_ns()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
_HEX_TIME_MANAGER = HexTimeManager()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def hex_zmq_ts_to_ns(ts: dict) -> int:
|
|
72
|
+
return ts['s'] * 1_000_000_000 + ts['ns']
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def ns_to_hex_zmq_ts(ns: int) -> dict:
|
|
26
76
|
return {
|
|
27
|
-
"s":
|
|
28
|
-
"ns":
|
|
77
|
+
"s": ns // 1_000_000_000,
|
|
78
|
+
"ns": ns % 1_000_000_000,
|
|
29
79
|
}
|
|
30
80
|
|
|
31
81
|
|
|
82
|
+
def hex_ns_now() -> int:
|
|
83
|
+
return _HEX_TIME_MANAGER.get_now_ns()
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def hex_zmq_ts_now() -> dict:
|
|
87
|
+
return ns_to_hex_zmq_ts(hex_ns_now())
|
|
88
|
+
|
|
89
|
+
|
|
32
90
|
def hex_zmq_ts_delta_ms(curr_ts, hdr_ts) -> float:
|
|
33
91
|
try:
|
|
34
92
|
return (curr_ts['s'] - hdr_ts['s']) * 1_000 + (
|
|
@@ -52,7 +110,7 @@ class HexRate:
|
|
|
52
110
|
|
|
53
111
|
@staticmethod
|
|
54
112
|
def __now_ns() -> int:
|
|
55
|
-
return
|
|
113
|
+
return hex_ns_now()
|
|
56
114
|
|
|
57
115
|
def reset(self):
|
|
58
116
|
self.__next_ns = self.__now_ns() + self.__period_ns
|
|
@@ -85,28 +143,6 @@ class HexRate:
|
|
|
85
143
|
# ZMQ Related
|
|
86
144
|
################################################################
|
|
87
145
|
|
|
88
|
-
|
|
89
|
-
class HexSafeValue:
|
|
90
|
-
|
|
91
|
-
def __init__(self):
|
|
92
|
-
self.__value = None
|
|
93
|
-
self.__ready = threading.Event()
|
|
94
|
-
self.__lock = threading.Lock()
|
|
95
|
-
|
|
96
|
-
def set(self, value):
|
|
97
|
-
with self.__lock:
|
|
98
|
-
self.__value = value
|
|
99
|
-
self.__ready.set()
|
|
100
|
-
|
|
101
|
-
def get(self, timeout_s=1.0):
|
|
102
|
-
if (not self.__ready.is_set()) and timeout_s > 0.0:
|
|
103
|
-
print(f"no value yet, waiting for {timeout_s}s")
|
|
104
|
-
self.__ready.wait(timeout_s)
|
|
105
|
-
|
|
106
|
-
with self.__lock:
|
|
107
|
-
return self.__value
|
|
108
|
-
|
|
109
|
-
|
|
110
146
|
NET_CONFIG = {
|
|
111
147
|
"ip": "127.0.0.1",
|
|
112
148
|
"port": 12345,
|
|
@@ -137,6 +173,13 @@ class HexZMQClientBase(ABC):
|
|
|
137
173
|
self._lock = threading.Lock()
|
|
138
174
|
self.__make_socket()
|
|
139
175
|
|
|
176
|
+
# receive thread
|
|
177
|
+
self._recv_thread = threading.Thread(
|
|
178
|
+
target=self._recv_loop,
|
|
179
|
+
daemon=True,
|
|
180
|
+
)
|
|
181
|
+
self._recv_flag = False
|
|
182
|
+
|
|
140
183
|
def __del__(self):
|
|
141
184
|
self.close()
|
|
142
185
|
|
|
@@ -171,9 +214,12 @@ class HexZMQClientBase(ABC):
|
|
|
171
214
|
self.__make_socket()
|
|
172
215
|
return resp_hdr, resp_buf
|
|
173
216
|
|
|
174
|
-
def is_working(self):
|
|
217
|
+
def is_working(self) -> bool:
|
|
175
218
|
working_hdr, _ = self.request({"cmd": "is_working"})
|
|
176
|
-
|
|
219
|
+
if working_hdr is None:
|
|
220
|
+
return False
|
|
221
|
+
else:
|
|
222
|
+
return working_hdr["cmd"] == "is_working_ok"
|
|
177
223
|
|
|
178
224
|
def __send_req(self, req_dict: dict, req_buf: np.ndarray | None = None):
|
|
179
225
|
# construct send header
|
|
@@ -220,12 +266,30 @@ class HexZMQClientBase(ABC):
|
|
|
220
266
|
return None, None
|
|
221
267
|
|
|
222
268
|
def close(self):
|
|
269
|
+
self._recv_flag = False
|
|
270
|
+
self._recv_thread.join()
|
|
223
271
|
if self._socket is not None:
|
|
224
272
|
try:
|
|
225
273
|
self._socket.close(0)
|
|
226
274
|
except Exception:
|
|
227
275
|
pass
|
|
228
276
|
|
|
277
|
+
def _wait_for_working(self, timeout: float = 5.0):
|
|
278
|
+
for _ in range(int(timeout * 10)):
|
|
279
|
+
if self.is_working():
|
|
280
|
+
if hasattr(self, "seq_clear"):
|
|
281
|
+
self.seq_clear()
|
|
282
|
+
break
|
|
283
|
+
else:
|
|
284
|
+
time.sleep(0.1)
|
|
285
|
+
self._recv_flag = True
|
|
286
|
+
self._recv_thread.start()
|
|
287
|
+
|
|
288
|
+
@abstractmethod
|
|
289
|
+
def _recv_loop(self):
|
|
290
|
+
raise NotImplementedError(
|
|
291
|
+
"`_receive_thread` should be implemented by the child class")
|
|
292
|
+
|
|
229
293
|
|
|
230
294
|
class HexZMQServerBase(ABC):
|
|
231
295
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hex_zmq_servers
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: HEXFELLOW ZMQ Servers
|
|
5
5
|
Author-email: Dong Zhaorui <joray.dong@hexfellow.com>
|
|
6
6
|
Maintainer-email: jecjune <zejun.chen@hexfellow.com>, Dong Zhaorui <joray.dong@hexfellow.com>
|
|
@@ -26,16 +26,17 @@ Requires-Dist: pyzmq>=27.0.1
|
|
|
26
26
|
Requires-Dist: hex_device<1.4.0,>=1.3.1
|
|
27
27
|
Requires-Dist: hex_robo_utils<0.3.0,>=0.2.0
|
|
28
28
|
Requires-Dist: dynamixel-sdk==3.8.4
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
Requires-Dist:
|
|
29
|
+
Requires-Dist: opencv-python>=4.2
|
|
30
|
+
Provides-Extra: berxel
|
|
31
|
+
Requires-Dist: berxel_py_wrapper>=2.0.182; extra == "berxel"
|
|
32
|
+
Provides-Extra: realsense
|
|
33
|
+
Requires-Dist: pyrealsense2>=2.56.5.9235; extra == "realsense"
|
|
32
34
|
Provides-Extra: mujoco
|
|
33
35
|
Requires-Dist: mujoco>=3.3.3; extra == "mujoco"
|
|
34
|
-
Requires-Dist: opencv-python>=4.2; extra == "mujoco"
|
|
35
36
|
Provides-Extra: all
|
|
36
37
|
Requires-Dist: berxel_py_wrapper>=2.0.182; extra == "all"
|
|
37
38
|
Requires-Dist: mujoco>=3.3.3; extra == "all"
|
|
38
|
-
Requires-Dist:
|
|
39
|
+
Requires-Dist: pyrealsense2>=2.56.5.9235; extra == "all"
|
|
39
40
|
Dynamic: license-file
|
|
40
41
|
|
|
41
42
|
# hex_zmq_servers
|
|
@@ -1,33 +1,43 @@
|
|
|
1
|
-
hex_zmq_servers/__init__.py,sha256=
|
|
2
|
-
hex_zmq_servers/device_base.py,sha256=
|
|
1
|
+
hex_zmq_servers/__init__.py,sha256=1dnB9YTRq5uAFHo_3dMp1t1UxS4ZrcuZ_7CzBwqAfEM,5426
|
|
2
|
+
hex_zmq_servers/device_base.py,sha256=dABpeUg84Au-vtbVzvnv1Tmn_898CNOkIvH2UDUnV3I,1191
|
|
3
3
|
hex_zmq_servers/hex_launch.py,sha256=opS_WwntAzV3UjOCVBo7FaLVW_dP3jlO40q-gFSBy68,17543
|
|
4
|
-
hex_zmq_servers/zmq_base.py,sha256=
|
|
5
|
-
hex_zmq_servers/cam/__init__.py,sha256=
|
|
6
|
-
hex_zmq_servers/cam/cam_base.py,sha256=
|
|
4
|
+
hex_zmq_servers/zmq_base.py,sha256=RFRvl95oci6d-urP5n-qGDh5090pZ5q7Oy8_vNPqJxI,16380
|
|
5
|
+
hex_zmq_servers/cam/__init__.py,sha256=hZ4NTEaO9uxcBua-nyJTpXxmk_GiIAcK2uWz3QQbwvE,1408
|
|
6
|
+
hex_zmq_servers/cam/cam_base.py,sha256=3INQUYzzue4B0EiLEuo8IZDfLTifjmqXpXIkPaNA7dY,5134
|
|
7
7
|
hex_zmq_servers/cam/berxel/__init__.py,sha256=3fK06RWAS_q8a_3z-RxFTv32e99og-4dMZTxH08TOcY,508
|
|
8
|
-
hex_zmq_servers/cam/berxel/cam_berxel.py,sha256=
|
|
9
|
-
hex_zmq_servers/cam/berxel/cam_berxel_cli.py,sha256=
|
|
8
|
+
hex_zmq_servers/cam/berxel/cam_berxel.py,sha256=l7SGnMUsM4D8HqHrJM9_QSyvLeNSRSDb37-_tSNHF-c,9035
|
|
9
|
+
hex_zmq_servers/cam/berxel/cam_berxel_cli.py,sha256=ZbtZ4fjO0MCjqstfCxJwH1sMAtHKFKFIg9QI1zxplMQ,811
|
|
10
10
|
hex_zmq_servers/cam/berxel/cam_berxel_srv.py,sha256=8QPhPpRsYnbbIFTQAT3sZA1nRTq1XpKg-GmD6ERUu9w,2311
|
|
11
11
|
hex_zmq_servers/cam/dummy/__init__.py,sha256=EziQ8H8d9Vm1AYw4YryIumTXpx-lwEnlfzTl7VAnKHM,499
|
|
12
|
-
hex_zmq_servers/cam/dummy/cam_dummy.py,sha256=
|
|
13
|
-
hex_zmq_servers/cam/dummy/cam_dummy_cli.py,sha256=
|
|
12
|
+
hex_zmq_servers/cam/dummy/cam_dummy.py,sha256=pWw0ceVCcKS9BJdD3JjGAAtSc1sqmYsL2UyGhmwVI7M,1898
|
|
13
|
+
hex_zmq_servers/cam/dummy/cam_dummy_cli.py,sha256=kA5eJiF4VRcOTFFB0rdtXBT0SuT2fb9GMK7J8vGkafw,690
|
|
14
14
|
hex_zmq_servers/cam/dummy/cam_dummy_srv.py,sha256=rUcTA00cSi3Hju1NrT8dp-8WRp7rYcREgVRESC8na0U,1986
|
|
15
|
+
hex_zmq_servers/cam/realsense/__init__.py,sha256=huwWPmO3ACxg6vMvjul6Ty0HDdwwfk886M4-DU5Z_04,535
|
|
16
|
+
hex_zmq_servers/cam/realsense/cam_realsense.py,sha256=NIMjVDgLVFGGbNOcckfEukYoX1BThRxFqgg7mef38T8,5147
|
|
17
|
+
hex_zmq_servers/cam/realsense/cam_realsense_cli.py,sha256=qKx0PvsWtKbxYd-SOaEWFkpIHhPP8QDRzvTuUA9QKoc,814
|
|
18
|
+
hex_zmq_servers/cam/realsense/cam_realsense_srv.py,sha256=2NqXp96pu-LvBs91rNM-BJgbznD_COPcc8ZFeNxdGdw,2320
|
|
19
|
+
hex_zmq_servers/cam/rgb/__init__.py,sha256=cBrms_3YOQAp2ZtfvHkuaxqameSG1bALDgUcNrDpEQA,481
|
|
20
|
+
hex_zmq_servers/cam/rgb/cam_rgb.py,sha256=qYIfJS2bCckAXkn1lsw4XBvb4e2BbGtkhTVR6GvJZcA,4784
|
|
21
|
+
hex_zmq_servers/cam/rgb/cam_rgb_cli.py,sha256=fWshI38ShDCML6Mu9WmLI543as_kxBmP0nj8LBhM7FI,1084
|
|
22
|
+
hex_zmq_servers/cam/rgb/cam_rgb_srv.py,sha256=gsJBpcboRMGDZ1jviHDhFNhw8UWKzGsAY92dNzizW6Q,2266
|
|
15
23
|
hex_zmq_servers/config/cam_berxel.json,sha256=G-eps3r7seBEMQEzxk1p1ObsBxmvageGbPdvtZ8gRe4,340
|
|
16
24
|
hex_zmq_servers/config/cam_dummy.json,sha256=T6vCG9__Gos9M5seK7w43xbqttAI6P1iyjcB_W0AOu8,191
|
|
17
|
-
hex_zmq_servers/config/
|
|
18
|
-
hex_zmq_servers/config/
|
|
25
|
+
hex_zmq_servers/config/cam_realsense.json,sha256=hEQw-fdzC0w49kgcaqf_VwLj_RKB27PGOupQ2f2ig_k,321
|
|
26
|
+
hex_zmq_servers/config/cam_rgb.json,sha256=EDPE9xYBRVqPiw5x_0F_zR1It9Q5Uo3HSV6PW9lsu28,491
|
|
27
|
+
hex_zmq_servers/config/mujoco_archer_y6.json,sha256=okinjE_oFpXeII9hDzoBJivTkwJ-8XLUq6XUms00lGc,669
|
|
28
|
+
hex_zmq_servers/config/mujoco_e3_desktop.json,sha256=IVvGgGOEbrU1cQmXuCdsgpvyyzKhTFAgVccG_8Lxnoc,735
|
|
19
29
|
hex_zmq_servers/config/robot_dummy.json,sha256=mBKWmLz4S7K6fP0zYDImKPfnR6lerRjEv6Ore0jYQMQ,2963
|
|
20
30
|
hex_zmq_servers/config/robot_gello.json,sha256=pXPAng92M_-dhnLbh1R_LXKeskSapSnoJhNS-u2dhvo,1157
|
|
21
|
-
hex_zmq_servers/config/robot_hexarm.json,sha256=
|
|
31
|
+
hex_zmq_servers/config/robot_hexarm.json,sha256=VckqMsZ9aeYVxkNHWBPYIIMKsQHDc3gSYLptP5aFLzg,690
|
|
22
32
|
hex_zmq_servers/config/zmq_dummy.json,sha256=T6vCG9__Gos9M5seK7w43xbqttAI6P1iyjcB_W0AOu8,191
|
|
23
33
|
hex_zmq_servers/mujoco/__init__.py,sha256=OKG7aJ2BACpob_DuAvikLiRo4M_3DO9Ffapwen87k_0,870
|
|
24
|
-
hex_zmq_servers/mujoco/mujoco_base.py,sha256=
|
|
34
|
+
hex_zmq_servers/mujoco/mujoco_base.py,sha256=e3QkZfxlE8MHPse1nKgTlCHvV-mNYfMMuZ7PtmyVVsA,11752
|
|
25
35
|
hex_zmq_servers/mujoco/archer_y6/__init__.py,sha256=v1vApZ-qBLEcqFjDN0eff5kvkzO3s8QHBO4AitBODfc,559
|
|
26
|
-
hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6.py,sha256=
|
|
27
|
-
hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6_cli.py,sha256=
|
|
28
|
-
hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6_srv.py,sha256=
|
|
29
|
-
hex_zmq_servers/mujoco/archer_y6/model/robot.xml,sha256=
|
|
30
|
-
hex_zmq_servers/mujoco/archer_y6/model/scene.xml,sha256=
|
|
36
|
+
hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6.py,sha256=viZI_bVbnWbhow86mKQ10Sb8PAfsriw5uNFhRgGwR4U,12073
|
|
37
|
+
hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6_cli.py,sha256=xNn_tF1U49ECjYvhy3xq1KizXZ5qJyqCNdPtBEVJyTU,2074
|
|
38
|
+
hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6_srv.py,sha256=Pn51_bXLAa40cTMKpCvqU7aT1jpR_r9pMrW2subLHAs,4987
|
|
39
|
+
hex_zmq_servers/mujoco/archer_y6/model/robot.xml,sha256=U6Rrpfb0jhd8UMuZzY6YmmZVF6QFrU4vVJqQ7MoRsgI,8172
|
|
40
|
+
hex_zmq_servers/mujoco/archer_y6/model/scene.xml,sha256=00mk4AMmgE0vhHdxuZ6MkKqOBu0Nf17T7GudlpJNI1I,2122
|
|
31
41
|
hex_zmq_servers/mujoco/archer_y6/model/setting.xml,sha256=4jhxau8xeYtnnMmvy6B79B8-w2HbK_PTGDHyIelDEQs,1997
|
|
32
42
|
hex_zmq_servers/mujoco/archer_y6/model/assets/arm_base_link.STL,sha256=JUr1vVN2qyB05yAJHwEKXQ1zpZ4m7_Cw-LbVaC9_gEE,413584
|
|
33
43
|
hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_1.STL,sha256=4tx8OgJT-yNsHLAUUU6G2sfnNlVy36G2OrLmy9jcJ_0,304784
|
|
@@ -46,11 +56,11 @@ hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_right_link_1.STL,sha256=fj
|
|
|
46
56
|
hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_right_link_2.STL,sha256=ucyn656VxBpRx3sshxLxMPJIUZfNfEQ90P-9b8sR0xg,80284
|
|
47
57
|
hex_zmq_servers/mujoco/archer_y6/model/assets/table_link.STL,sha256=dqFXHRqjZSDyvYHCaJkbmYFsKngZRk1xjg_Zl2_jDc4,684
|
|
48
58
|
hex_zmq_servers/mujoco/e3_desktop/__init__.py,sha256=pMLKpJGBHgc9IU142NcM7ubwdXq9E422k6Giui1A8i4,565
|
|
49
|
-
hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop.py,sha256=
|
|
50
|
-
hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop_cli.py,sha256=
|
|
51
|
-
hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop_srv.py,sha256=
|
|
52
|
-
hex_zmq_servers/mujoco/e3_desktop/model/robot.xml,sha256=
|
|
53
|
-
hex_zmq_servers/mujoco/e3_desktop/model/scene.xml,sha256=
|
|
59
|
+
hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop.py,sha256=kLHb7HIevv7j4S-gwFJJ1G0XWN6eIa6rq8tXYHI7IzE,17918
|
|
60
|
+
hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop_cli.py,sha256=AHmsX3cZx4iZX7q8itFVqvCGeiy_JQ4AsTzdyXLCR9E,7790
|
|
61
|
+
hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop_srv.py,sha256=dFGGmwHihrMDzAD1uptL91O9W1l7mKZRUlEWLkAZ7xU,8953
|
|
62
|
+
hex_zmq_servers/mujoco/e3_desktop/model/robot.xml,sha256=hLp385sG037rw2bAPu6tKoa5XYQLwWb4YawijYr7Ebs,17030
|
|
63
|
+
hex_zmq_servers/mujoco/e3_desktop/model/scene.xml,sha256=8zs5vCf_RvB1wUlD9ymVMpxyU2Eq0XzqEQnXm_wHhdA,2222
|
|
54
64
|
hex_zmq_servers/mujoco/e3_desktop/model/setting.xml,sha256=Y-GIwzWi46SJsBQZs0g0G7MDuzQmCGbHaVmdPZGYL14,4472
|
|
55
65
|
hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_base_link.STL,sha256=JUr1vVN2qyB05yAJHwEKXQ1zpZ4m7_Cw-LbVaC9_gEE,413584
|
|
56
66
|
hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_1.STL,sha256=4tx8OgJT-yNsHLAUUU6G2sfnNlVy36G2OrLmy9jcJ_0,304784
|
|
@@ -70,18 +80,18 @@ hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_right_link_1.STL,sha256=f
|
|
|
70
80
|
hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_right_link_2.STL,sha256=ucyn656VxBpRx3sshxLxMPJIUZfNfEQ90P-9b8sR0xg,80284
|
|
71
81
|
hex_zmq_servers/mujoco/e3_desktop/model/assets/table_link.STL,sha256=dqFXHRqjZSDyvYHCaJkbmYFsKngZRk1xjg_Zl2_jDc4,684
|
|
72
82
|
hex_zmq_servers/robot/__init__.py,sha256=PqzGhsdbaeyYa7EZpAYMvT9myYhCO3OTbSPXVp1uiUM,1026
|
|
73
|
-
hex_zmq_servers/robot/robot_base.py,sha256
|
|
83
|
+
hex_zmq_servers/robot/robot_base.py,sha256=-or25jU3x7kJaIx2c7l83nPLqb93yL4IHIWjfDGkivo,8064
|
|
74
84
|
hex_zmq_servers/robot/dummy/__init__.py,sha256=_lDtPH-JQ1ltPB8JzD7wLu77iwNOgEZ3fJkz8MNKXrw,517
|
|
75
|
-
hex_zmq_servers/robot/dummy/robot_dummy.py,sha256=
|
|
76
|
-
hex_zmq_servers/robot/dummy/robot_dummy_cli.py,sha256=
|
|
85
|
+
hex_zmq_servers/robot/dummy/robot_dummy.py,sha256=vZTrEvIFsW5ne123hEGoynLGnQH2T-jxLBVww6LEwfM,2665
|
|
86
|
+
hex_zmq_servers/robot/dummy/robot_dummy_cli.py,sha256=kjugt5By71Nj0wFb2tnQgRdSyYYZeUomwh96UCCR-No,699
|
|
77
87
|
hex_zmq_servers/robot/dummy/robot_dummy_srv.py,sha256=E0a0arRgAQiCfEXnrJ1l6TP8Cijy497WfX--padg7B8,2576
|
|
78
88
|
hex_zmq_servers/robot/gello/__init__.py,sha256=7xSTc8ZB-bQODyEo6pzPz3ILZ1eAgVSsy6BmF2ECKeQ,517
|
|
79
|
-
hex_zmq_servers/robot/gello/robot_gello.py,sha256=
|
|
80
|
-
hex_zmq_servers/robot/gello/robot_gello_cli.py,sha256=
|
|
89
|
+
hex_zmq_servers/robot/gello/robot_gello.py,sha256=DyMELg490HykRYdbs4QVluR8oC7KAYWAju0OEmaowPE,13100
|
|
90
|
+
hex_zmq_servers/robot/gello/robot_gello_cli.py,sha256=wnbRVrpIEE8G4ZzfjuSJA5TMPig-2I1oLJE-6b0kFSY,699
|
|
81
91
|
hex_zmq_servers/robot/gello/robot_gello_srv.py,sha256=vCWgKpsO4MhZLspdaG45uHj8EB0gnptuj2SuxCaoEVI,2841
|
|
82
92
|
hex_zmq_servers/robot/hexarm/__init__.py,sha256=07EUc2fCKqxYZbUUcDeD_AXvCAWI6r1qBjpWJ58_AcY,1414
|
|
83
|
-
hex_zmq_servers/robot/hexarm/robot_hexarm.py,sha256=
|
|
84
|
-
hex_zmq_servers/robot/hexarm/robot_hexarm_cli.py,sha256=
|
|
93
|
+
hex_zmq_servers/robot/hexarm/robot_hexarm.py,sha256=dUd_6JSHvlEIxkYLF1xCBZTOOcxt_VcfS2qcb-vEkgU,10364
|
|
94
|
+
hex_zmq_servers/robot/hexarm/robot_hexarm_cli.py,sha256=KO-I_CCjWwdckRKlxX7gIxUgsUKW3rcOycBo1nAxFEY,852
|
|
85
95
|
hex_zmq_servers/robot/hexarm/robot_hexarm_srv.py,sha256=PE_WyLRXV_DbYVVQ0Wd60KlZZ37vfoEJVEhf2_4xADQ,2759
|
|
86
96
|
hex_zmq_servers/robot/hexarm/urdf/archer_l6y/empty.urdf,sha256=g7Yn_uIM_ddb_K32FnDgHWSsvxH08oaPDiMb0yUb0Lg,7808
|
|
87
97
|
hex_zmq_servers/robot/hexarm/urdf/archer_l6y/gp100.urdf,sha256=YJ_S1Hfwg_PV1nr5QZJuikuCO18GqNu6RDA3gEwG-Pk,7620
|
|
@@ -93,8 +103,8 @@ hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100.urdf,sha256=i8vpARxlQpYskLmTZ7
|
|
|
93
103
|
hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100_handle.urdf,sha256=Tpii1Wk26jRtMqLWI2knrqBTIh7hCjpgGySlrBgdvpA,7458
|
|
94
104
|
hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100_p050.urdf,sha256=6Zzc_PXDwtxw9xQEXQOH0hu_moaiQzeMC22hUqAQS9s,7459
|
|
95
105
|
hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100_p050_handle.urdf,sha256=HNa7wweNYUj8YtSUfx87ASeNEIPIjB-gZ4O7RyHng6g,7456
|
|
96
|
-
hex_zmq_servers-0.3.
|
|
97
|
-
hex_zmq_servers-0.3.
|
|
98
|
-
hex_zmq_servers-0.3.
|
|
99
|
-
hex_zmq_servers-0.3.
|
|
100
|
-
hex_zmq_servers-0.3.
|
|
106
|
+
hex_zmq_servers-0.3.4.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
|
|
107
|
+
hex_zmq_servers-0.3.4.dist-info/METADATA,sha256=vlE6l40uTHq955ndiXzA52hwcjhW7CvLfbPxwVx7Y6c,4750
|
|
108
|
+
hex_zmq_servers-0.3.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
109
|
+
hex_zmq_servers-0.3.4.dist-info/top_level.txt,sha256=lPH1DfgMrQOe0Grh8zSZopf6LmnLvb_aStVmZ41PyAg,16
|
|
110
|
+
hex_zmq_servers-0.3.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|