hex-zmq-servers 0.3.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hex_zmq_servers/__init__.py +173 -0
- hex_zmq_servers/cam/__init__.py +52 -0
- hex_zmq_servers/cam/berxel/__init__.py +17 -0
- hex_zmq_servers/cam/berxel/cam_berxel.py +282 -0
- hex_zmq_servers/cam/berxel/cam_berxel_cli.py +33 -0
- hex_zmq_servers/cam/berxel/cam_berxel_srv.py +79 -0
- hex_zmq_servers/cam/cam_base.py +189 -0
- hex_zmq_servers/cam/dummy/__init__.py +17 -0
- hex_zmq_servers/cam/dummy/cam_dummy.py +69 -0
- hex_zmq_servers/cam/dummy/cam_dummy_cli.py +29 -0
- hex_zmq_servers/cam/dummy/cam_dummy_srv.py +68 -0
- hex_zmq_servers/cam/realsense/__init__.py +17 -0
- hex_zmq_servers/cam/realsense/cam_realsense.py +159 -0
- hex_zmq_servers/cam/realsense/cam_realsense_cli.py +33 -0
- hex_zmq_servers/cam/realsense/cam_realsense_srv.py +78 -0
- hex_zmq_servers/cam/rgb/__init__.py +17 -0
- hex_zmq_servers/cam/rgb/cam_rgb.py +135 -0
- hex_zmq_servers/cam/rgb/cam_rgb_cli.py +43 -0
- hex_zmq_servers/cam/rgb/cam_rgb_srv.py +78 -0
- hex_zmq_servers/config/cam_berxel.json +18 -0
- hex_zmq_servers/config/cam_dummy.json +12 -0
- hex_zmq_servers/config/cam_realsense.json +17 -0
- hex_zmq_servers/config/cam_rgb.json +28 -0
- hex_zmq_servers/config/mujoco_archer_y6.json +37 -0
- hex_zmq_servers/config/mujoco_e3_desktop.json +41 -0
- hex_zmq_servers/config/robot_dummy.json +153 -0
- hex_zmq_servers/config/robot_gello.json +66 -0
- hex_zmq_servers/config/robot_hexarm.json +37 -0
- hex_zmq_servers/config/zmq_dummy.json +12 -0
- hex_zmq_servers/device_base.py +44 -0
- hex_zmq_servers/hex_launch.py +489 -0
- hex_zmq_servers/mujoco/__init__.py +28 -0
- hex_zmq_servers/mujoco/archer_y6/__init__.py +17 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/arm_base_link.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_1.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_2.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_3.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_4.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_5.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/assets.xml +17 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/camera_link.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_base_link.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_left_helper_link.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_left_link_1.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_left_link_2.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_right_helper_link.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_right_link_1.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_right_link_2.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/assets/table_link.STL +0 -0
- hex_zmq_servers/mujoco/archer_y6/model/robot.xml +95 -0
- hex_zmq_servers/mujoco/archer_y6/model/scene.xml +51 -0
- hex_zmq_servers/mujoco/archer_y6/model/setting.xml +37 -0
- hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6.py +325 -0
- hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6_cli.py +71 -0
- hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6_srv.py +148 -0
- hex_zmq_servers/mujoco/e3_desktop/__init__.py +17 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_base_link.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_1.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_2.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_3.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_4.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_5.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/assets.xml +18 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/camera_link.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/e3_desktop_base_link.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_base_link.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_left_helper_link.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_left_link_1.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_left_link_2.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_right_helper_link.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_right_link_1.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_right_link_2.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/assets/table_link.STL +0 -0
- hex_zmq_servers/mujoco/e3_desktop/model/robot.xml +188 -0
- hex_zmq_servers/mujoco/e3_desktop/model/scene.xml +53 -0
- hex_zmq_servers/mujoco/e3_desktop/model/setting.xml +72 -0
- hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop.py +449 -0
- hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop_cli.py +289 -0
- hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop_srv.py +244 -0
- hex_zmq_servers/mujoco/mujoco_base.py +425 -0
- hex_zmq_servers/robot/__init__.py +37 -0
- hex_zmq_servers/robot/dummy/__init__.py +17 -0
- hex_zmq_servers/robot/dummy/robot_dummy.py +94 -0
- hex_zmq_servers/robot/dummy/robot_dummy_cli.py +29 -0
- hex_zmq_servers/robot/dummy/robot_dummy_srv.py +82 -0
- hex_zmq_servers/robot/gello/__init__.py +17 -0
- hex_zmq_servers/robot/gello/robot_gello.py +366 -0
- hex_zmq_servers/robot/gello/robot_gello_cli.py +29 -0
- hex_zmq_servers/robot/gello/robot_gello_srv.py +93 -0
- hex_zmq_servers/robot/hexarm/__init__.py +47 -0
- hex_zmq_servers/robot/hexarm/robot_hexarm.py +292 -0
- hex_zmq_servers/robot/hexarm/robot_hexarm_cli.py +37 -0
- hex_zmq_servers/robot/hexarm/robot_hexarm_srv.py +87 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_l6y/empty.urdf +206 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_l6y/gp100.urdf +206 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_l6y/gp100_handle.urdf +206 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_l6y/gp100_p050.urdf +206 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_l6y/gp100_p050_handle.urdf +206 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_y6/empty.urdf +207 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100.urdf +207 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100_handle.urdf +207 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100_p050.urdf +207 -0
- hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100_p050_handle.urdf +207 -0
- hex_zmq_servers/robot/robot_base.py +276 -0
- hex_zmq_servers/zmq_base.py +547 -0
- hex_zmq_servers-0.3.9.dist-info/METADATA +147 -0
- hex_zmq_servers-0.3.9.dist-info/RECORD +110 -0
- hex_zmq_servers-0.3.9.dist-info/WHEEL +5 -0
- hex_zmq_servers-0.3.9.dist-info/licenses/LICENSE +201 -0
- hex_zmq_servers-0.3.9.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding:utf-8 -*-
|
|
3
|
+
################################################################
|
|
4
|
+
# Copyright 2025 Dong Zhaorui. All rights reserved.
|
|
5
|
+
# Author: Dong Zhaorui 847235539@qq.com
|
|
6
|
+
# Date : 2025-09-16
|
|
7
|
+
################################################################
|
|
8
|
+
|
|
9
|
+
import threading
|
|
10
|
+
import numpy as np
|
|
11
|
+
from collections import deque
|
|
12
|
+
from abc import abstractmethod
|
|
13
|
+
|
|
14
|
+
from ..device_base import HexDeviceBase
|
|
15
|
+
from ..zmq_base import HexZMQClientBase, HexZMQServerBase, HexRate
|
|
16
|
+
|
|
17
|
+
NET_CONFIG = {
|
|
18
|
+
"ip": "127.0.0.1",
|
|
19
|
+
"port": 12345,
|
|
20
|
+
"realtime_mode": False,
|
|
21
|
+
"deque_maxlen": 10,
|
|
22
|
+
"client_timeout_ms": 200,
|
|
23
|
+
"server_timeout_ms": 1_000,
|
|
24
|
+
"server_num_workers": 4,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class HexCamBase(HexDeviceBase):
|
|
29
|
+
|
|
30
|
+
def __init__(self, realtime_mode: bool = False):
|
|
31
|
+
HexDeviceBase.__init__(self, realtime_mode)
|
|
32
|
+
|
|
33
|
+
def __del__(self):
|
|
34
|
+
HexDeviceBase.__del__(self)
|
|
35
|
+
|
|
36
|
+
@abstractmethod
|
|
37
|
+
def work_loop(self, hex_queues: list[deque | threading.Event]):
|
|
38
|
+
raise NotImplementedError(
|
|
39
|
+
"`work_loop` should be implemented by the child class")
|
|
40
|
+
|
|
41
|
+
@abstractmethod
|
|
42
|
+
def close(self):
|
|
43
|
+
raise NotImplementedError(
|
|
44
|
+
"`close` should be implemented by the child class")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class HexCamClientBase(HexZMQClientBase):
|
|
48
|
+
|
|
49
|
+
def __init__(self, net_config: dict = NET_CONFIG):
|
|
50
|
+
HexZMQClientBase.__init__(self, net_config)
|
|
51
|
+
self._rgb_seq = 0
|
|
52
|
+
self._used_rgb_seq = 0
|
|
53
|
+
self._depth_seq = 0
|
|
54
|
+
self._used_depth_seq = 0
|
|
55
|
+
self._rgb_queue = deque(maxlen=self._deque_maxlen)
|
|
56
|
+
self._depth_queue = deque(maxlen=self._deque_maxlen)
|
|
57
|
+
|
|
58
|
+
def __del__(self):
|
|
59
|
+
HexZMQClientBase.__del__(self)
|
|
60
|
+
|
|
61
|
+
def get_rgb(self, newest: bool = False):
|
|
62
|
+
try:
|
|
63
|
+
if self._realtime_mode or newest:
|
|
64
|
+
hdr, img = self._rgb_queue[-1]
|
|
65
|
+
if self._used_rgb_seq != hdr["args"]:
|
|
66
|
+
self._used_rgb_seq = hdr["args"]
|
|
67
|
+
return hdr, img
|
|
68
|
+
else:
|
|
69
|
+
return None, None
|
|
70
|
+
else:
|
|
71
|
+
return self._rgb_queue.popleft()
|
|
72
|
+
except IndexError:
|
|
73
|
+
return None, None
|
|
74
|
+
|
|
75
|
+
def get_depth(self, newest: bool = False):
|
|
76
|
+
try:
|
|
77
|
+
if self._realtime_mode or newest:
|
|
78
|
+
hdr, img = self._depth_queue[-1]
|
|
79
|
+
if self._used_depth_seq != hdr["args"]:
|
|
80
|
+
self._used_depth_seq = hdr["args"]
|
|
81
|
+
return hdr, img
|
|
82
|
+
else:
|
|
83
|
+
return None, None
|
|
84
|
+
else:
|
|
85
|
+
return self._depth_queue.popleft()
|
|
86
|
+
except IndexError:
|
|
87
|
+
return None, None
|
|
88
|
+
|
|
89
|
+
def _get_rgb_inner(self):
|
|
90
|
+
return self._process_frame(False)
|
|
91
|
+
|
|
92
|
+
def _get_depth_inner(self):
|
|
93
|
+
return self._process_frame(True)
|
|
94
|
+
|
|
95
|
+
def _process_frame(self, depth_flag: bool):
|
|
96
|
+
req_cmd = f"get_{'depth' if depth_flag else 'rgb'}"
|
|
97
|
+
hdr, img = self.request({
|
|
98
|
+
"cmd":
|
|
99
|
+
req_cmd,
|
|
100
|
+
"args": (1 + (self._depth_seq if depth_flag else self._rgb_seq)) %
|
|
101
|
+
self._max_seq_num,
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
try:
|
|
105
|
+
cmd = hdr["cmd"]
|
|
106
|
+
if cmd == f"{req_cmd}_ok":
|
|
107
|
+
if depth_flag:
|
|
108
|
+
self._depth_seq = hdr["args"]
|
|
109
|
+
else:
|
|
110
|
+
self._rgb_seq = hdr["args"]
|
|
111
|
+
return hdr, img
|
|
112
|
+
else:
|
|
113
|
+
return None, None
|
|
114
|
+
except KeyError:
|
|
115
|
+
print(f"\033[91m{hdr['cmd']} requires `cmd`\033[0m")
|
|
116
|
+
return None, None
|
|
117
|
+
except Exception as e:
|
|
118
|
+
print(f"\033[91m__process_frame failed: {e}\033[0m")
|
|
119
|
+
return None, None
|
|
120
|
+
|
|
121
|
+
def _recv_loop(self):
|
|
122
|
+
rate = HexRate(200)
|
|
123
|
+
while self._recv_flag:
|
|
124
|
+
hdr, img = self._get_rgb_inner()
|
|
125
|
+
if hdr is not None:
|
|
126
|
+
self._rgb_queue.append((hdr, img))
|
|
127
|
+
hdr, img = self._get_depth_inner()
|
|
128
|
+
if hdr is not None:
|
|
129
|
+
self._depth_queue.append((hdr, img))
|
|
130
|
+
rate.sleep()
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class HexCamServerBase(HexZMQServerBase):
|
|
134
|
+
|
|
135
|
+
def __init__(self, net_config: dict = NET_CONFIG):
|
|
136
|
+
HexZMQServerBase.__init__(self, net_config)
|
|
137
|
+
self._device: HexDeviceBase = None
|
|
138
|
+
self._rgb_queue = deque(maxlen=self._deque_maxlen)
|
|
139
|
+
self._depth_queue = deque(maxlen=self._deque_maxlen)
|
|
140
|
+
|
|
141
|
+
def __del__(self):
|
|
142
|
+
HexZMQServerBase.__del__(self)
|
|
143
|
+
self._device.close()
|
|
144
|
+
|
|
145
|
+
def work_loop(self):
|
|
146
|
+
try:
|
|
147
|
+
self._device.work_loop([
|
|
148
|
+
self._rgb_queue,
|
|
149
|
+
self._depth_queue,
|
|
150
|
+
self._stop_event,
|
|
151
|
+
])
|
|
152
|
+
finally:
|
|
153
|
+
self._device.close()
|
|
154
|
+
|
|
155
|
+
def _get_frame(self, recv_hdr: dict, depth_flag: bool):
|
|
156
|
+
try:
|
|
157
|
+
seq = recv_hdr["args"]
|
|
158
|
+
except KeyError:
|
|
159
|
+
print(f"\033[91m{recv_hdr['cmd']} requires `args`\033[0m")
|
|
160
|
+
return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
|
|
161
|
+
|
|
162
|
+
try:
|
|
163
|
+
if depth_flag:
|
|
164
|
+
ts, count, img = self._depth_queue[
|
|
165
|
+
-1] if self._realtime_mode else self._depth_queue.popleft(
|
|
166
|
+
)
|
|
167
|
+
else:
|
|
168
|
+
ts, count, img = self._rgb_queue[
|
|
169
|
+
-1] if self._realtime_mode else self._rgb_queue.popleft()
|
|
170
|
+
except IndexError:
|
|
171
|
+
return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
|
|
172
|
+
except Exception as e:
|
|
173
|
+
print(f"\033[91m{recv_hdr['cmd']} failed: {e}\033[0m")
|
|
174
|
+
return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
|
|
175
|
+
|
|
176
|
+
delta = (count - seq) % self._max_seq_num
|
|
177
|
+
if delta >= 0 and delta < 1e6:
|
|
178
|
+
return {
|
|
179
|
+
"cmd": f"{recv_hdr['cmd']}_ok",
|
|
180
|
+
"ts": ts,
|
|
181
|
+
"args": count
|
|
182
|
+
}, img
|
|
183
|
+
else:
|
|
184
|
+
return {"cmd": f"{recv_hdr['cmd']}_failed"}, None
|
|
185
|
+
|
|
186
|
+
@abstractmethod
|
|
187
|
+
def _process_request(self, recv_hdr: dict, recv_buf: np.ndarray):
|
|
188
|
+
raise NotImplementedError(
|
|
189
|
+
"`_process_request` should be implemented by the child class")
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding:utf-8 -*-
|
|
3
|
+
################################################################
|
|
4
|
+
# Copyright 2025 Dong Zhaorui. All rights reserved.
|
|
5
|
+
# Author: Dong Zhaorui 847235539@qq.com
|
|
6
|
+
# Date : 2025-09-12
|
|
7
|
+
################################################################
|
|
8
|
+
|
|
9
|
+
from .cam_dummy import HexCamDummy
|
|
10
|
+
from .cam_dummy_cli import HexCamDummyClient
|
|
11
|
+
from .cam_dummy_srv import HexCamDummyServer
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"HexCamDummy",
|
|
15
|
+
"HexCamDummyClient",
|
|
16
|
+
"HexCamDummyServer",
|
|
17
|
+
]
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding:utf-8 -*-
|
|
3
|
+
################################################################
|
|
4
|
+
# Copyright 2025 Dong Zhaorui. All rights reserved.
|
|
5
|
+
# Author: Dong Zhaorui 847235539@qq.com
|
|
6
|
+
# Date : 2025-09-12
|
|
7
|
+
################################################################
|
|
8
|
+
|
|
9
|
+
import threading
|
|
10
|
+
import numpy as np
|
|
11
|
+
from collections import deque
|
|
12
|
+
|
|
13
|
+
from ..cam_base import HexCamBase
|
|
14
|
+
from ...zmq_base import (
|
|
15
|
+
hex_zmq_ts_now,
|
|
16
|
+
HexRate,
|
|
17
|
+
)
|
|
18
|
+
from ...hex_launch import hex_log, HEX_LOG_LEVEL
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class HexCamDummy(HexCamBase):
|
|
22
|
+
|
|
23
|
+
def __init__(self, params_config: dict = {}, realtime_mode: bool = False):
|
|
24
|
+
HexCamBase.__init__(self, realtime_mode)
|
|
25
|
+
self._working.set()
|
|
26
|
+
|
|
27
|
+
def __del__(self):
|
|
28
|
+
HexCamBase.__del__(self)
|
|
29
|
+
|
|
30
|
+
def work_loop(self, hex_queues: list[deque | threading.Event]):
|
|
31
|
+
rgb_queue = hex_queues[0]
|
|
32
|
+
depth_queue = hex_queues[1]
|
|
33
|
+
stop_event = hex_queues[2]
|
|
34
|
+
|
|
35
|
+
rgb_count = 0
|
|
36
|
+
depth_count = 0
|
|
37
|
+
rate = HexRate(60)
|
|
38
|
+
while self._working.is_set() and not stop_event.is_set():
|
|
39
|
+
# rgb
|
|
40
|
+
rgb_img = np.random.randint(
|
|
41
|
+
0,
|
|
42
|
+
255,
|
|
43
|
+
(480, 640, 3),
|
|
44
|
+
dtype=np.uint8,
|
|
45
|
+
)
|
|
46
|
+
rgb_queue.append((hex_zmq_ts_now(), rgb_count, rgb_img))
|
|
47
|
+
rgb_count = (rgb_count + 1) % self._max_seq_num
|
|
48
|
+
|
|
49
|
+
# depth
|
|
50
|
+
depth_img = np.random.randint(
|
|
51
|
+
0,
|
|
52
|
+
65535,
|
|
53
|
+
(480, 640),
|
|
54
|
+
dtype=np.uint16,
|
|
55
|
+
)
|
|
56
|
+
depth_queue.append((hex_zmq_ts_now(), depth_count, depth_img))
|
|
57
|
+
depth_count = (depth_count + 1) % self._max_seq_num
|
|
58
|
+
|
|
59
|
+
# sleep
|
|
60
|
+
rate.sleep()
|
|
61
|
+
|
|
62
|
+
# close
|
|
63
|
+
self.close()
|
|
64
|
+
|
|
65
|
+
def close(self):
|
|
66
|
+
if not self._working.is_set():
|
|
67
|
+
return
|
|
68
|
+
self._working.clear()
|
|
69
|
+
hex_log(HEX_LOG_LEVEL["info"], "HexCamDummy closed")
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding:utf-8 -*-
|
|
3
|
+
################################################################
|
|
4
|
+
# Copyright 2025 Dong Zhaorui. All rights reserved.
|
|
5
|
+
# Author: Dong Zhaorui 847235539@qq.com
|
|
6
|
+
# Date : 2025-09-12
|
|
7
|
+
################################################################
|
|
8
|
+
|
|
9
|
+
from ..cam_base import HexCamClientBase
|
|
10
|
+
|
|
11
|
+
NET_CONFIG = {
|
|
12
|
+
"ip": "127.0.0.1",
|
|
13
|
+
"port": 12345,
|
|
14
|
+
"realtime_mode": False,
|
|
15
|
+
"deque_maxlen": 10,
|
|
16
|
+
"client_timeout_ms": 200,
|
|
17
|
+
"server_timeout_ms": 1_000,
|
|
18
|
+
"server_num_workers": 4,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class HexCamDummyClient(HexCamClientBase):
|
|
23
|
+
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
net_config: dict = NET_CONFIG,
|
|
27
|
+
):
|
|
28
|
+
HexCamClientBase.__init__(self, net_config)
|
|
29
|
+
self._wait_for_working()
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding:utf-8 -*-
|
|
3
|
+
################################################################
|
|
4
|
+
# Copyright 2025 Dong Zhaorui. All rights reserved.
|
|
5
|
+
# Author: Dong Zhaorui 847235539@qq.com
|
|
6
|
+
# Date : 2025-09-12
|
|
7
|
+
################################################################
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
from ..cam_base import HexCamServerBase
|
|
13
|
+
from .cam_dummy import HexCamDummy
|
|
14
|
+
except (ImportError, ValueError):
|
|
15
|
+
import sys
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
this_file = Path(__file__).resolve()
|
|
18
|
+
project_root = this_file.parents[3]
|
|
19
|
+
if str(project_root) not in sys.path:
|
|
20
|
+
sys.path.insert(0, str(project_root))
|
|
21
|
+
from hex_zmq_servers.cam.cam_base import HexCamServerBase
|
|
22
|
+
from hex_zmq_servers.cam.dummy.cam_dummy import HexCamDummy
|
|
23
|
+
|
|
24
|
+
NET_CONFIG = {
|
|
25
|
+
"ip": "127.0.0.1",
|
|
26
|
+
"port": 12345,
|
|
27
|
+
"realtime_mode": False,
|
|
28
|
+
"deque_maxlen": 10,
|
|
29
|
+
"client_timeout_ms": 200,
|
|
30
|
+
"server_timeout_ms": 1_000,
|
|
31
|
+
"server_num_workers": 4,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class HexCamDummyServer(HexCamServerBase):
|
|
36
|
+
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
net_config: dict = NET_CONFIG,
|
|
40
|
+
params_config: dict = {},
|
|
41
|
+
):
|
|
42
|
+
HexCamServerBase.__init__(self, net_config)
|
|
43
|
+
|
|
44
|
+
# camera
|
|
45
|
+
self._device = HexCamDummy(params_config,
|
|
46
|
+
net_config.get("realtime_mode", False))
|
|
47
|
+
|
|
48
|
+
def _process_request(self, recv_hdr: dict, recv_buf: np.ndarray):
|
|
49
|
+
if recv_hdr["cmd"] == "is_working":
|
|
50
|
+
return self.no_ts_hdr(recv_hdr, self._device.is_working()), None
|
|
51
|
+
elif recv_hdr["cmd"] == "get_rgb":
|
|
52
|
+
return self._get_frame(recv_hdr, False)
|
|
53
|
+
elif recv_hdr["cmd"] == "get_depth":
|
|
54
|
+
return self._get_frame(recv_hdr, True)
|
|
55
|
+
else:
|
|
56
|
+
raise ValueError(f"unknown command: {recv_hdr['cmd']}")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
if __name__ == "__main__":
|
|
60
|
+
import argparse, json
|
|
61
|
+
from hex_zmq_servers.zmq_base import hex_server_helper
|
|
62
|
+
|
|
63
|
+
parser = argparse.ArgumentParser()
|
|
64
|
+
parser.add_argument("--cfg", type=str, required=True)
|
|
65
|
+
args = parser.parse_args()
|
|
66
|
+
cfg = json.loads(args.cfg)
|
|
67
|
+
|
|
68
|
+
hex_server_helper(cfg, HexCamDummyServer)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding:utf-8 -*-
|
|
3
|
+
################################################################
|
|
4
|
+
# Copyright 2025 Dong Zhaorui. All rights reserved.
|
|
5
|
+
# Author: Dong Zhaorui 847235539@qq.com
|
|
6
|
+
# Date : 2025-09-12
|
|
7
|
+
################################################################
|
|
8
|
+
|
|
9
|
+
from .cam_realsense import HexCamRealsense
|
|
10
|
+
from .cam_realsense_cli import HexCamRealsenseClient
|
|
11
|
+
from .cam_realsense_srv import HexCamRealsenseServer
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"HexCamRealsense",
|
|
15
|
+
"HexCamRealsenseClient",
|
|
16
|
+
"HexCamRealsenseServer",
|
|
17
|
+
]
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding:utf-8 -*-
|
|
3
|
+
################################################################
|
|
4
|
+
# Copyright 2025 Dong Zhaorui. All rights reserved.
|
|
5
|
+
# Author: Dong Zhaorui 847235539@qq.com
|
|
6
|
+
# Date : 2025-09-14
|
|
7
|
+
################################################################
|
|
8
|
+
|
|
9
|
+
import threading
|
|
10
|
+
import numpy as np
|
|
11
|
+
from collections import deque
|
|
12
|
+
|
|
13
|
+
from ..cam_base import HexCamBase
|
|
14
|
+
from ...zmq_base import (
|
|
15
|
+
hex_ns_now,
|
|
16
|
+
hex_zmq_ts_now,
|
|
17
|
+
hex_zmq_ts_delta_ms,
|
|
18
|
+
)
|
|
19
|
+
from ...hex_launch import hex_log, HEX_LOG_LEVEL
|
|
20
|
+
import pyrealsense2 as rs
|
|
21
|
+
|
|
22
|
+
CAMERA_CONFIG = {
|
|
23
|
+
"serial_number": '243422073194',
|
|
24
|
+
"resolution": [640, 480],
|
|
25
|
+
"frame_rate": 30,
|
|
26
|
+
"sens_ts": True,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class HexCamRealsense(HexCamBase):
|
|
31
|
+
|
|
32
|
+
def __init__(
|
|
33
|
+
self,
|
|
34
|
+
camera_config: dict = CAMERA_CONFIG,
|
|
35
|
+
realtime_mode: bool = False,
|
|
36
|
+
):
|
|
37
|
+
HexCamBase.__init__(self, realtime_mode)
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
self.__serial_number = camera_config["serial_number"]
|
|
41
|
+
self.__resolution = camera_config["resolution"]
|
|
42
|
+
self.__frame_rate = camera_config["frame_rate"]
|
|
43
|
+
self.__sens_ts = camera_config["sens_ts"]
|
|
44
|
+
except KeyError as ke:
|
|
45
|
+
missing_key = ke.args[0]
|
|
46
|
+
raise ValueError(
|
|
47
|
+
f"camera_config is not valid, missing key: {missing_key}")
|
|
48
|
+
|
|
49
|
+
# variables
|
|
50
|
+
# realsense variables
|
|
51
|
+
ctx = rs.context()
|
|
52
|
+
serial_numbers = []
|
|
53
|
+
for dev in ctx.query_devices():
|
|
54
|
+
serial = dev.get_info(rs.camera_info.serial_number)
|
|
55
|
+
name = dev.get_info(rs.camera_info.name)
|
|
56
|
+
print(f" - Device: {name}, Serial: {serial}")
|
|
57
|
+
serial_numbers.append(serial)
|
|
58
|
+
if self.__serial_number not in serial_numbers:
|
|
59
|
+
print(
|
|
60
|
+
f"can not find device with serial number: {self.__serial_number}"
|
|
61
|
+
)
|
|
62
|
+
return
|
|
63
|
+
|
|
64
|
+
# camera variables
|
|
65
|
+
self.__intri = np.zeros(4)
|
|
66
|
+
|
|
67
|
+
# open device
|
|
68
|
+
self.__pipeline = rs.pipeline()
|
|
69
|
+
config = rs.config()
|
|
70
|
+
config.enable_device(self.__serial_number)
|
|
71
|
+
config.enable_stream(
|
|
72
|
+
rs.stream.color,
|
|
73
|
+
self.__resolution[0],
|
|
74
|
+
self.__resolution[1],
|
|
75
|
+
rs.format.bgr8,
|
|
76
|
+
self.__frame_rate,
|
|
77
|
+
)
|
|
78
|
+
config.enable_stream(
|
|
79
|
+
rs.stream.depth,
|
|
80
|
+
self.__resolution[0],
|
|
81
|
+
self.__resolution[1],
|
|
82
|
+
rs.format.z16,
|
|
83
|
+
self.__frame_rate,
|
|
84
|
+
)
|
|
85
|
+
profile = self.__pipeline.start(config)
|
|
86
|
+
color_profile = profile.get_stream(rs.stream.color)
|
|
87
|
+
color_intrinsics = color_profile.as_video_stream_profile(
|
|
88
|
+
).get_intrinsics()
|
|
89
|
+
self.__intri[0] = color_intrinsics.fx
|
|
90
|
+
self.__intri[1] = color_intrinsics.fy
|
|
91
|
+
self.__intri[2] = color_intrinsics.ppx
|
|
92
|
+
self.__intri[3] = color_intrinsics.ppy
|
|
93
|
+
self.__align = rs.align(rs.stream.color)
|
|
94
|
+
self.__bias_ns = None
|
|
95
|
+
|
|
96
|
+
# start work loop
|
|
97
|
+
self._working.set()
|
|
98
|
+
|
|
99
|
+
def get_intri(self) -> np.ndarray:
|
|
100
|
+
self._wait_for_working()
|
|
101
|
+
return self.__intri
|
|
102
|
+
|
|
103
|
+
def get_serial_number(self) -> np.ndarray:
|
|
104
|
+
self._wait_for_working()
|
|
105
|
+
return self.__serial_number
|
|
106
|
+
|
|
107
|
+
def work_loop(self, hex_queues: list[deque | threading.Event]):
|
|
108
|
+
rgb_queue = hex_queues[0]
|
|
109
|
+
depth_queue = hex_queues[1]
|
|
110
|
+
stop_event = hex_queues[2]
|
|
111
|
+
|
|
112
|
+
frames = self.__pipeline.wait_for_frames()
|
|
113
|
+
bias_ns = np.int64(hex_ns_now()) - np.int64(
|
|
114
|
+
frames.get_frame_metadata(rs.frame_metadata_value.sensor_timestamp)
|
|
115
|
+
* 1_000)
|
|
116
|
+
|
|
117
|
+
rgb_count = 0
|
|
118
|
+
depth_count = 0
|
|
119
|
+
while self._working.is_set() and not stop_event.is_set():
|
|
120
|
+
# read frame
|
|
121
|
+
aligned_frames = self.__align.process(
|
|
122
|
+
self.__pipeline.wait_for_frames())
|
|
123
|
+
cur_ns = hex_zmq_ts_now()
|
|
124
|
+
sen_ts_ns = bias_ns + np.int64(
|
|
125
|
+
aligned_frames.get_frame_metadata(
|
|
126
|
+
rs.frame_metadata_value.sensor_timestamp) * 1_000)
|
|
127
|
+
sen_ts = {
|
|
128
|
+
"s": sen_ts_ns // 1_000_000_000,
|
|
129
|
+
"ns": sen_ts_ns % 1_000_000_000,
|
|
130
|
+
}
|
|
131
|
+
if hex_zmq_ts_delta_ms(cur_ns, sen_ts) < 0:
|
|
132
|
+
sen_ts = cur_ns
|
|
133
|
+
|
|
134
|
+
# collect rgb frame
|
|
135
|
+
color_frame = aligned_frames.get_color_frame()
|
|
136
|
+
if color_frame:
|
|
137
|
+
|
|
138
|
+
rgb_queue.append(
|
|
139
|
+
(sen_ts if self.__sens_ts else cur_ns, rgb_count,
|
|
140
|
+
np.asanyarray(color_frame.get_data())))
|
|
141
|
+
rgb_count = (rgb_count + 1) % self._max_seq_num
|
|
142
|
+
|
|
143
|
+
# collect depth frame
|
|
144
|
+
depth_frame = aligned_frames.get_depth_frame()
|
|
145
|
+
if depth_frame:
|
|
146
|
+
depth_queue.append(
|
|
147
|
+
(sen_ts if self.__sens_ts else cur_ns, depth_count,
|
|
148
|
+
np.asanyarray(depth_frame.get_data())))
|
|
149
|
+
depth_count = (depth_count + 1) % self._max_seq_num
|
|
150
|
+
|
|
151
|
+
# close
|
|
152
|
+
self.close()
|
|
153
|
+
|
|
154
|
+
def close(self):
|
|
155
|
+
if not self._working.is_set():
|
|
156
|
+
return
|
|
157
|
+
self._working.clear()
|
|
158
|
+
self.__pipeline.stop()
|
|
159
|
+
hex_log(HEX_LOG_LEVEL["info"], "HexCamRealsense closed")
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding:utf-8 -*-
|
|
3
|
+
################################################################
|
|
4
|
+
# Copyright 2025 Dong Zhaorui. All rights reserved.
|
|
5
|
+
# Author: Dong Zhaorui 847235539@qq.com
|
|
6
|
+
# Date : 2025-09-12
|
|
7
|
+
################################################################
|
|
8
|
+
|
|
9
|
+
from ..cam_base import HexCamClientBase
|
|
10
|
+
|
|
11
|
+
NET_CONFIG = {
|
|
12
|
+
"ip": "127.0.0.1",
|
|
13
|
+
"port": 12345,
|
|
14
|
+
"realtime_mode": False,
|
|
15
|
+
"deque_maxlen": 10,
|
|
16
|
+
"client_timeout_ms": 200,
|
|
17
|
+
"server_timeout_ms": 1_000,
|
|
18
|
+
"server_num_workers": 4,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class HexCamRealsenseClient(HexCamClientBase):
|
|
23
|
+
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
net_config: dict = NET_CONFIG,
|
|
27
|
+
):
|
|
28
|
+
HexCamClientBase.__init__(self, net_config)
|
|
29
|
+
self._wait_for_working()
|
|
30
|
+
|
|
31
|
+
def get_intri(self):
|
|
32
|
+
intri_hdr, intri = self.request({"cmd": "get_intri"})
|
|
33
|
+
return intri_hdr, intri
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding:utf-8 -*-
|
|
3
|
+
################################################################
|
|
4
|
+
# Copyright 2025 Dong Zhaorui. All rights reserved.
|
|
5
|
+
# Author: Dong Zhaorui 847235539@qq.com
|
|
6
|
+
# Date : 2025-09-12
|
|
7
|
+
################################################################
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
from ..cam_base import HexCamServerBase
|
|
13
|
+
from .cam_realsense import HexCamRealsense
|
|
14
|
+
except (ImportError, ValueError):
|
|
15
|
+
import sys
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
this_file = Path(__file__).resolve()
|
|
18
|
+
project_root = this_file.parents[3]
|
|
19
|
+
if str(project_root) not in sys.path:
|
|
20
|
+
sys.path.insert(0, str(project_root))
|
|
21
|
+
from hex_zmq_servers.cam.cam_base import HexCamServerBase
|
|
22
|
+
from hex_zmq_servers.cam.realsense.cam_realsense import HexCamRealsense
|
|
23
|
+
|
|
24
|
+
NET_CONFIG = {
|
|
25
|
+
"ip": "127.0.0.1",
|
|
26
|
+
"port": 12345,
|
|
27
|
+
"realtime_mode": False,
|
|
28
|
+
"deque_maxlen": 10,
|
|
29
|
+
"client_timeout_ms": 200,
|
|
30
|
+
"server_timeout_ms": 1_000,
|
|
31
|
+
"server_num_workers": 4,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
CAMERA_CONFIG = {
|
|
35
|
+
"serial_number": '243422073194',
|
|
36
|
+
"resolution": [640, 480],
|
|
37
|
+
"frame_rate": 30,
|
|
38
|
+
"sens_ts": True,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class HexCamRealsenseServer(HexCamServerBase):
|
|
43
|
+
|
|
44
|
+
def __init__(
|
|
45
|
+
self,
|
|
46
|
+
net_config: dict = NET_CONFIG,
|
|
47
|
+
params_config: dict = CAMERA_CONFIG,
|
|
48
|
+
):
|
|
49
|
+
HexCamServerBase.__init__(self, net_config)
|
|
50
|
+
|
|
51
|
+
# camera
|
|
52
|
+
self._device = HexCamRealsense(params_config,
|
|
53
|
+
net_config.get("realtime_mode", False))
|
|
54
|
+
|
|
55
|
+
def _process_request(self, recv_hdr: dict, recv_buf: np.ndarray):
|
|
56
|
+
if recv_hdr["cmd"] == "is_working":
|
|
57
|
+
return self.no_ts_hdr(recv_hdr, self._device.is_working()), None
|
|
58
|
+
elif recv_hdr["cmd"] == "get_intri":
|
|
59
|
+
intri = self._device.get_intri()
|
|
60
|
+
return self.no_ts_hdr(recv_hdr, intri is not None), intri
|
|
61
|
+
elif recv_hdr["cmd"] == "get_rgb":
|
|
62
|
+
return self._get_frame(recv_hdr, False)
|
|
63
|
+
elif recv_hdr["cmd"] == "get_depth":
|
|
64
|
+
return self._get_frame(recv_hdr, True)
|
|
65
|
+
else:
|
|
66
|
+
raise ValueError(f"unknown command: {recv_hdr['cmd']}")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
if __name__ == "__main__":
|
|
70
|
+
import argparse, json
|
|
71
|
+
from hex_zmq_servers.zmq_base import hex_server_helper
|
|
72
|
+
|
|
73
|
+
parser = argparse.ArgumentParser()
|
|
74
|
+
parser.add_argument("--cfg", type=str, required=True)
|
|
75
|
+
args = parser.parse_args()
|
|
76
|
+
cfg = json.loads(args.cfg)
|
|
77
|
+
|
|
78
|
+
hex_server_helper(cfg, HexCamRealsenseServer)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding:utf-8 -*-
|
|
3
|
+
################################################################
|
|
4
|
+
# Copyright 2025 Dong Zhaorui. All rights reserved.
|
|
5
|
+
# Author: Dong Zhaorui 847235539@qq.com
|
|
6
|
+
# Date : 2025-09-12
|
|
7
|
+
################################################################
|
|
8
|
+
|
|
9
|
+
from .cam_rgb import HexCamRGB
|
|
10
|
+
from .cam_rgb_cli import HexCamRGBClient
|
|
11
|
+
from .cam_rgb_srv import HexCamRGBServer
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"HexCamRGB",
|
|
15
|
+
"HexCamRGBClient",
|
|
16
|
+
"HexCamRGBServer",
|
|
17
|
+
]
|