hex-zmq-servers 0.3.2__py3-none-any.whl → 0.3.3__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.
@@ -18,6 +18,10 @@ from .robot import HexRobotDummy, HexRobotDummyClient, HexRobotDummyServer
18
18
  from .robot import HexRobotGello, HexRobotGelloClient, HexRobotGelloServer
19
19
  from .robot import HexRobotHexarm, HexRobotHexarmClient, HexRobotHexarmServer, HEXARM_URDF_PATH_DICT
20
20
 
21
+ from .cam import HexCamBase, HexCamClientBase, HexCamServerBase
22
+ from .cam import HexCamDummy, HexCamDummyClient, HexCamDummyServer
23
+ from .cam import HexCamRGB, HexCamRGBClient, HexCamRGBServer
24
+
21
25
  import os
22
26
 
23
27
  file_dir = os.path.dirname(os.path.abspath(__file__))
@@ -26,12 +30,16 @@ HEX_ZMQ_SERVERS_PATH_DICT = {
26
30
  "robot_dummy": f"{file_dir}/robot/dummy/robot_dummy_srv.py",
27
31
  "robot_gello": f"{file_dir}/robot/gello/robot_gello_srv.py",
28
32
  "robot_hexarm": f"{file_dir}/robot/hexarm/robot_hexarm_srv.py",
33
+ "cam_dummy": f"{file_dir}/cam/dummy/cam_dummy_srv.py",
34
+ "cam_rgb": f"{file_dir}/cam/rgb/cam_rgb_srv.py",
29
35
  }
30
36
  HEX_ZMQ_CONFIGS_PATH_DICT = {
31
37
  "zmq_dummy": f"{file_dir}/config/zmq_dummy.json",
32
38
  "robot_dummy": f"{file_dir}/config/robot_dummy.json",
33
39
  "robot_gello": f"{file_dir}/config/robot_gello.json",
34
40
  "robot_hexarm": f"{file_dir}/config/robot_hexarm.json",
41
+ "cam_dummy": f"{file_dir}/config/cam_dummy.json",
42
+ "cam_rgb": f"{file_dir}/config/cam_rgb.json",
35
43
  }
36
44
 
37
45
  __all__ = [
@@ -76,47 +84,62 @@ __all__ = [
76
84
  "HexRobotHexarm",
77
85
  "HexRobotHexarmClient",
78
86
  "HexRobotHexarmServer",
87
+
88
+ # camera
89
+ "HexCamBase",
90
+ "HexCamClientBase",
91
+ "HexCamServerBase",
92
+ "HexCamDummy",
93
+ "HexCamDummyClient",
94
+ "HexCamDummyServer",
95
+ "HexCamRGB",
96
+ "HexCamRGBClient",
97
+ "HexCamRGBServer",
79
98
  ]
80
99
 
81
100
  # Check optional dependencies availability
82
101
  from importlib.util import find_spec
83
102
 
84
- _HAS_OPENCV = find_spec("cv2") is not None
85
103
  _HAS_BERXEL = find_spec("berxel_py_wrapper") is not None
104
+ _HAS_REALSENSE = find_spec("pyrealsense2") is not None
86
105
  _HAS_MUJOCO = find_spec("mujoco") is not None
87
106
 
88
- # Optional: camera
89
- if _HAS_OPENCV and _HAS_BERXEL:
90
- from .cam import HexCamBase, HexCamClientBase, HexCamServerBase
91
- from .cam import HexCamDummy, HexCamDummyClient, HexCamDummyServer
107
+ # Optional: berxel
108
+ if _HAS_BERXEL:
92
109
  from .cam import HexCamBerxel, HexCamBerxelClient, HexCamBerxelServer
93
110
  HEX_ZMQ_SERVERS_PATH_DICT.update({
94
- "cam_dummy":
95
- f"{file_dir}/cam/dummy/cam_dummy_srv.py",
96
111
  "cam_berxel":
97
112
  f"{file_dir}/cam/berxel/cam_berxel_srv.py",
98
113
  })
99
114
  HEX_ZMQ_CONFIGS_PATH_DICT.update({
100
- "cam_dummy":
101
- f"{file_dir}/config/cam_dummy.json",
102
115
  "cam_berxel":
103
116
  f"{file_dir}/config/cam_berxel.json",
104
117
  })
105
118
  __all__.extend([
106
- # camera
107
- "HexCamBase",
108
- "HexCamClientBase",
109
- "HexCamServerBase",
110
- "HexCamDummy",
111
- "HexCamDummyClient",
112
- "HexCamDummyServer",
113
119
  "HexCamBerxel",
114
120
  "HexCamBerxelClient",
115
121
  "HexCamBerxelServer",
116
122
  ])
117
123
 
124
+ # Optional: realsense
125
+ if _HAS_REALSENSE:
126
+ from .cam import HexCamRealsense, HexCamRealsenseClient, HexCamRealsenseServer
127
+ HEX_ZMQ_SERVERS_PATH_DICT.update({
128
+ "cam_realsense":
129
+ f"{file_dir}/cam/realsense/cam_realsense_srv.py",
130
+ })
131
+ HEX_ZMQ_CONFIGS_PATH_DICT.update({
132
+ "cam_realsense":
133
+ f"{file_dir}/config/cam_realsense.json",
134
+ })
135
+ __all__.extend([
136
+ "HexCamRealsense",
137
+ "HexCamRealsenseClient",
138
+ "HexCamRealsenseServer",
139
+ ])
140
+
118
141
  # Optional: mujoco
119
- if _HAS_OPENCV and _HAS_MUJOCO:
142
+ if _HAS_MUJOCO:
120
143
  from .mujoco import HexMujocoBase, HexMujocoClientBase, HexMujocoServerBase
121
144
  from .mujoco import HexMujocoArcherY6, HexMujocoArcherY6Client, HexMujocoArcherY6Server
122
145
  from .mujoco import HexMujocoE3Desktop, HexMujocoE3DesktopClient, HexMujocoE3DesktopServer
@@ -8,7 +8,7 @@
8
8
 
9
9
  from .cam_base import HexCamBase, HexCamClientBase, HexCamServerBase
10
10
  from .dummy import HexCamDummy, HexCamDummyClient, HexCamDummyServer
11
- from .berxel import HexCamBerxel, HexCamBerxelClient, HexCamBerxelServer
11
+ from .rgb import HexCamRGB, HexCamRGBClient, HexCamRGBServer
12
12
 
13
13
  __all__ = [
14
14
  # base
@@ -21,8 +21,32 @@ __all__ = [
21
21
  "HexCamDummyClient",
22
22
  "HexCamDummyServer",
23
23
 
24
- # berxel
25
- "HexCamBerxel",
26
- "HexCamBerxelClient",
27
- "HexCamBerxelServer",
24
+ # rgb
25
+ "HexCamRGB",
26
+ "HexCamRGBClient",
27
+ "HexCamRGBServer",
28
28
  ]
29
+
30
+ # Check optional dependencies availability
31
+ from importlib.util import find_spec
32
+
33
+ _HAS_BERXEL = find_spec("berxel_py_wrapper") is not None
34
+ _HAS_REALSENSE = find_spec("pyrealsense2") is not None
35
+
36
+ # Optional: berxel
37
+ if _HAS_BERXEL:
38
+ from .berxel import HexCamBerxel, HexCamBerxelClient, HexCamBerxelServer
39
+ __all__.extend([
40
+ "HexCamBerxel",
41
+ "HexCamBerxelClient",
42
+ "HexCamBerxelServer",
43
+ ])
44
+
45
+ # Optional: realsense
46
+ if _HAS_REALSENSE:
47
+ from .realsense import HexCamRealsense, HexCamRealsenseClient, HexCamRealsenseServer
48
+ __all__.extend([
49
+ "HexCamRealsense",
50
+ "HexCamRealsenseClient",
51
+ "HexCamRealsenseServer",
52
+ ])
@@ -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,157 @@
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 time
10
+ import threading
11
+ import numpy as np
12
+
13
+ from ..cam_base import HexCamBase
14
+ from ...zmq_base import (
15
+ hex_zmq_ts_now,
16
+ hex_zmq_ts_delta_ms,
17
+ HexSafeValue,
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
+ ):
36
+ HexCamBase.__init__(self)
37
+
38
+ try:
39
+ self.__serial_number = camera_config["serial_number"]
40
+ self.__resolution = camera_config["resolution"]
41
+ self.__frame_rate = camera_config["frame_rate"]
42
+ self.__sens_ts = camera_config["sens_ts"]
43
+ except KeyError as ke:
44
+ missing_key = ke.args[0]
45
+ raise ValueError(
46
+ f"camera_config is not valid, missing key: {missing_key}")
47
+
48
+ # variables
49
+ # realsense variables
50
+ ctx = rs.context()
51
+ serial_numbers = []
52
+ for dev in ctx.query_devices():
53
+ serial = dev.get_info(rs.camera_info.serial_number)
54
+ name = dev.get_info(rs.camera_info.name)
55
+ print(f" - Device: {name}, Serial: {serial}")
56
+ serial_numbers.append(serial)
57
+ if self.__serial_number not in serial_numbers:
58
+ print(
59
+ f"can not find device with serial number: {self.__serial_number}"
60
+ )
61
+ return
62
+
63
+ # camera variables
64
+ self.__intri = np.zeros(4)
65
+
66
+ # open device
67
+ self.__pipeline = rs.pipeline()
68
+ config = rs.config()
69
+ config.enable_device(self.__serial_number)
70
+ config.enable_stream(
71
+ rs.stream.color,
72
+ self.__resolution[0],
73
+ self.__resolution[1],
74
+ rs.format.bgr8,
75
+ self.__frame_rate,
76
+ )
77
+ config.enable_stream(
78
+ rs.stream.depth,
79
+ self.__resolution[0],
80
+ self.__resolution[1],
81
+ rs.format.z16,
82
+ self.__frame_rate,
83
+ )
84
+ profile = self.__pipeline.start(config)
85
+ color_profile = profile.get_stream(rs.stream.color)
86
+ color_intrinsics = color_profile.as_video_stream_profile(
87
+ ).get_intrinsics()
88
+ self.__intri[0] = color_intrinsics.fx
89
+ self.__intri[1] = color_intrinsics.fy
90
+ self.__intri[2] = color_intrinsics.ppx
91
+ self.__intri[3] = color_intrinsics.ppy
92
+ self.__align = rs.align(rs.stream.color)
93
+ self.__bias_ns = None
94
+
95
+ # start work loop
96
+ self._working.set()
97
+
98
+ def get_intri(self) -> np.ndarray:
99
+ self._wait_for_working()
100
+ return self.__intri
101
+
102
+ def get_serial_number(self) -> np.ndarray:
103
+ self._wait_for_working()
104
+ return self.__serial_number
105
+
106
+ def work_loop(self, hex_values: list[HexSafeValue | threading.Event]):
107
+ rgb_value = hex_values[0]
108
+ depth_value = hex_values[1]
109
+ stop_event = hex_values[2]
110
+
111
+ frames = self.__pipeline.wait_for_frames()
112
+ bias_ns = np.int64(time.time_ns()) - np.int64(
113
+ frames.get_frame_metadata(rs.frame_metadata_value.sensor_timestamp)
114
+ * 1_000)
115
+
116
+ rgb_count = 0
117
+ depth_count = 0
118
+ while self._working.is_set() and not stop_event.is_set():
119
+ # read frame
120
+ aligned_frames = self.__align.process(
121
+ self.__pipeline.wait_for_frames())
122
+ cur_ns = hex_zmq_ts_now()
123
+ sen_ts_ns = bias_ns + np.int64(
124
+ aligned_frames.get_frame_metadata(
125
+ rs.frame_metadata_value.sensor_timestamp) * 1_000)
126
+ sen_ts = {
127
+ "s": sen_ts_ns // 1_000_000_000,
128
+ "ns": sen_ts_ns % 1_000_000_000,
129
+ }
130
+ if hex_zmq_ts_delta_ms(cur_ns, sen_ts) < 0:
131
+ sen_ts = cur_ns
132
+
133
+ # collect rgb frame
134
+ color_frame = aligned_frames.get_color_frame()
135
+ if color_frame:
136
+
137
+ rgb_value.set((sen_ts if self.__sens_ts else cur_ns, rgb_count,
138
+ np.asanyarray(color_frame.get_data())))
139
+ rgb_count = (rgb_count + 1) % self._max_seq_num
140
+
141
+ # collect depth frame
142
+ depth_frame = aligned_frames.get_depth_frame()
143
+ if depth_frame:
144
+ depth_value.set(
145
+ (sen_ts if self.__sens_ts else cur_ns, depth_count,
146
+ np.asanyarray(depth_frame.get_data())))
147
+ depth_count = (depth_count + 1) % self._max_seq_num
148
+
149
+ # close
150
+ self.close()
151
+
152
+ def close(self):
153
+ if not self._working.is_set():
154
+ return
155
+ self._working.clear()
156
+ self.__pipeline.stop()
157
+ hex_log(HEX_LOG_LEVEL["info"], "HexCamRealsense closed")
@@ -0,0 +1,30 @@
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
+ "client_timeout_ms": 200,
15
+ "server_timeout_ms": 1_000,
16
+ "server_num_workers": 4,
17
+ }
18
+
19
+
20
+ class HexCamRealsenseClient(HexCamClientBase):
21
+
22
+ def __init__(
23
+ self,
24
+ net_config: dict = NET_CONFIG,
25
+ ):
26
+ HexCamClientBase.__init__(self, net_config)
27
+
28
+ def get_intri(self):
29
+ intri_hdr, intri = self.request({"cmd": "get_intri"})
30
+ return intri_hdr, intri
@@ -0,0 +1,75 @@
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
+ "client_timeout_ms": 200,
28
+ "server_timeout_ms": 1_000,
29
+ "server_num_workers": 4,
30
+ }
31
+
32
+ CAMERA_CONFIG = {
33
+ "serial_number": '243422073194',
34
+ "resolution": [640, 480],
35
+ "frame_rate": 30,
36
+ "sens_ts": True,
37
+ }
38
+
39
+
40
+ class HexCamRealsenseServer(HexCamServerBase):
41
+
42
+ def __init__(
43
+ self,
44
+ net_config: dict = NET_CONFIG,
45
+ params_config: dict = CAMERA_CONFIG,
46
+ ):
47
+ HexCamServerBase.__init__(self, net_config)
48
+
49
+ # camera
50
+ self._device = HexCamRealsense(params_config)
51
+
52
+ def _process_request(self, recv_hdr: dict, recv_buf: np.ndarray):
53
+ if recv_hdr["cmd"] == "is_working":
54
+ return self.no_ts_hdr(recv_hdr, self._device.is_working()), None
55
+ elif recv_hdr["cmd"] == "get_intri":
56
+ intri = self._device.get_intri()
57
+ return self.no_ts_hdr(recv_hdr, intri is not None), intri
58
+ elif recv_hdr["cmd"] == "get_rgb":
59
+ return self._get_frame(recv_hdr, False)
60
+ elif recv_hdr["cmd"] == "get_depth":
61
+ return self._get_frame(recv_hdr, True)
62
+ else:
63
+ raise ValueError(f"unknown command: {recv_hdr['cmd']}")
64
+
65
+
66
+ if __name__ == "__main__":
67
+ import argparse, json
68
+ from hex_zmq_servers.zmq_base import hex_server_helper
69
+
70
+ parser = argparse.ArgumentParser()
71
+ parser.add_argument("--cfg", type=str, required=True)
72
+ args = parser.parse_args()
73
+ cfg = json.loads(args.cfg)
74
+
75
+ 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
+ ]
@@ -0,0 +1,107 @@
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 cv2
10
+ import threading
11
+ import numpy as np
12
+
13
+ from ..cam_base import HexCamBase
14
+ from ...zmq_base import (
15
+ hex_zmq_ts_now,
16
+ HexRate,
17
+ HexSafeValue,
18
+ )
19
+ from ...hex_launch import hex_log, HEX_LOG_LEVEL
20
+
21
+ CAMERA_CONFIG = {
22
+ "cam_path": "/dev/video0",
23
+ "resolution": [640, 480],
24
+ "frame_rate": 30,
25
+ "sens_ts": True,
26
+ }
27
+
28
+
29
+ class HexCamRGB(HexCamBase):
30
+
31
+ def __init__(
32
+ self,
33
+ camera_config: dict = CAMERA_CONFIG,
34
+ ):
35
+ HexCamBase.__init__(self)
36
+
37
+ try:
38
+ self.__cam_path = camera_config["cam_path"]
39
+ self.__resolution = camera_config["resolution"]
40
+ self.__frame_rate = camera_config["frame_rate"]
41
+ self.__sens_ts = camera_config["sens_ts"]
42
+ except KeyError as ke:
43
+ missing_key = ke.args[0]
44
+ raise ValueError(
45
+ f"camera_config is not valid, missing key: {missing_key}")
46
+
47
+ # variables
48
+ # camera variables
49
+ self.__cap = cv2.VideoCapture(self.__cam_path)
50
+ # camera variables
51
+ self.__intri = np.zeros(4)
52
+
53
+ # open device
54
+ self.__cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*"MJPG"))
55
+ self.__cap.set(cv2.CAP_PROP_FRAME_WIDTH, self.__resolution[0])
56
+ self.__cap.set(cv2.CAP_PROP_FRAME_HEIGHT, self.__resolution[1])
57
+ self.__cap.set(cv2.CAP_PROP_FPS, self.__frame_rate)
58
+
59
+ print("#############################")
60
+ print(
61
+ f"# Resolution: ({self.__cap.get(cv2.CAP_PROP_FRAME_WIDTH)}, {self.__cap.get(cv2.CAP_PROP_FRAME_HEIGHT)})"
62
+ )
63
+ print(f"# FPS: {self.__cap.get(cv2.CAP_PROP_FPS)}")
64
+ four_cc_int = int(self.__cap.get(cv2.CAP_PROP_FOURCC))
65
+ four_cc_str = chr(four_cc_int & 0xff) + chr(
66
+ (four_cc_int >> 8) & 0xff) + chr((four_cc_int >> 16) & 0xff) + chr(
67
+ (four_cc_int >> 24) & 0xff)
68
+ print(f"# FourCC: {four_cc_str}")
69
+ print("#############################")
70
+
71
+ # start work loop
72
+ self._working.set()
73
+
74
+ def get_intri(self) -> np.ndarray:
75
+ self._wait_for_working()
76
+ return self.__intri
77
+
78
+ def work_loop(self, hex_values: list[HexSafeValue | threading.Event]):
79
+ rgb_value = hex_values[0]
80
+ depth_value = hex_values[1]
81
+ stop_event = hex_values[2]
82
+
83
+ rgb_count = 0
84
+ depth_value.set((hex_zmq_ts_now(), 0,
85
+ np.zeros((self.__resolution[1], self.__resolution[0]),
86
+ dtype=np.uint16)))
87
+ rate = HexRate(self.__frame_rate * 5)
88
+ while self._working.is_set() and not stop_event.is_set():
89
+ # read frame
90
+ ret, frame = self.__cap.read()
91
+
92
+ # collect rgb frame
93
+ if ret:
94
+ rgb_value.set((hex_zmq_ts_now(), rgb_count, frame))
95
+ rgb_count = (rgb_count + 1) % self._max_seq_num
96
+
97
+ rate.sleep()
98
+
99
+ # close
100
+ self.close()
101
+
102
+ def close(self):
103
+ if not self._working.is_set():
104
+ return
105
+ self._working.clear()
106
+ self.__cap.release()
107
+ hex_log(HEX_LOG_LEVEL["info"], "HexCamRGB closed")
@@ -0,0 +1,30 @@
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
+ "client_timeout_ms": 200,
15
+ "server_timeout_ms": 1_000,
16
+ "server_num_workers": 4,
17
+ }
18
+
19
+
20
+ class HexCamRGBClient(HexCamClientBase):
21
+
22
+ def __init__(
23
+ self,
24
+ net_config: dict = NET_CONFIG,
25
+ ):
26
+ HexCamClientBase.__init__(self, net_config)
27
+
28
+ def get_intri(self):
29
+ intri_hdr, intri = self.request({"cmd": "get_intri"})
30
+ return intri_hdr, intri
@@ -0,0 +1,75 @@
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_rgb import HexCamRGB
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.rgb.cam_rgb import HexCamRGB
23
+
24
+ NET_CONFIG = {
25
+ "ip": "127.0.0.1",
26
+ "port": 12345,
27
+ "client_timeout_ms": 200,
28
+ "server_timeout_ms": 1_000,
29
+ "server_num_workers": 4,
30
+ }
31
+
32
+ CAMERA_CONFIG = {
33
+ "cam_path": "/dev/video0",
34
+ "resolution": [640, 480],
35
+ "frame_rate": 30,
36
+ "sens_ts": True,
37
+ }
38
+
39
+
40
+ class HexCamRGBServer(HexCamServerBase):
41
+
42
+ def __init__(
43
+ self,
44
+ net_config: dict = NET_CONFIG,
45
+ params_config: dict = CAMERA_CONFIG,
46
+ ):
47
+ HexCamServerBase.__init__(self, net_config)
48
+
49
+ # camera
50
+ self._device = HexCamRGB(params_config)
51
+
52
+ def _process_request(self, recv_hdr: dict, recv_buf: np.ndarray):
53
+ if recv_hdr["cmd"] == "is_working":
54
+ return self.no_ts_hdr(recv_hdr, self._device.is_working()), None
55
+ elif recv_hdr["cmd"] == "get_intri":
56
+ intri = self._device.get_intri()
57
+ return self.no_ts_hdr(recv_hdr, intri is not None), intri
58
+ elif recv_hdr["cmd"] == "get_rgb":
59
+ return self._get_frame(recv_hdr, False)
60
+ elif recv_hdr["cmd"] == "get_depth":
61
+ return self._get_frame(recv_hdr, True)
62
+ else:
63
+ raise ValueError(f"unknown command: {recv_hdr['cmd']}")
64
+
65
+
66
+ if __name__ == "__main__":
67
+ import argparse, json
68
+ from hex_zmq_servers.zmq_base import hex_server_helper
69
+
70
+ parser = argparse.ArgumentParser()
71
+ parser.add_argument("--cfg", type=str, required=True)
72
+ args = parser.parse_args()
73
+ cfg = json.loads(args.cfg)
74
+
75
+ hex_server_helper(cfg, HexCamRGBServer)
@@ -0,0 +1,15 @@
1
+ {
2
+ "net": {
3
+ "ip": "127.0.0.1",
4
+ "port": 12345,
5
+ "client_timeout_ms": 200,
6
+ "server_timeout_ms": 1000,
7
+ "server_num_workers": 4
8
+ },
9
+ "params": {
10
+ "serial_number": "243422073194",
11
+ "resolution": [640, 480],
12
+ "frame_rate": 30,
13
+ "sens_ts": true
14
+ }
15
+ }