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.
Files changed (110) hide show
  1. hex_zmq_servers/__init__.py +173 -0
  2. hex_zmq_servers/cam/__init__.py +52 -0
  3. hex_zmq_servers/cam/berxel/__init__.py +17 -0
  4. hex_zmq_servers/cam/berxel/cam_berxel.py +282 -0
  5. hex_zmq_servers/cam/berxel/cam_berxel_cli.py +33 -0
  6. hex_zmq_servers/cam/berxel/cam_berxel_srv.py +79 -0
  7. hex_zmq_servers/cam/cam_base.py +189 -0
  8. hex_zmq_servers/cam/dummy/__init__.py +17 -0
  9. hex_zmq_servers/cam/dummy/cam_dummy.py +69 -0
  10. hex_zmq_servers/cam/dummy/cam_dummy_cli.py +29 -0
  11. hex_zmq_servers/cam/dummy/cam_dummy_srv.py +68 -0
  12. hex_zmq_servers/cam/realsense/__init__.py +17 -0
  13. hex_zmq_servers/cam/realsense/cam_realsense.py +159 -0
  14. hex_zmq_servers/cam/realsense/cam_realsense_cli.py +33 -0
  15. hex_zmq_servers/cam/realsense/cam_realsense_srv.py +78 -0
  16. hex_zmq_servers/cam/rgb/__init__.py +17 -0
  17. hex_zmq_servers/cam/rgb/cam_rgb.py +135 -0
  18. hex_zmq_servers/cam/rgb/cam_rgb_cli.py +43 -0
  19. hex_zmq_servers/cam/rgb/cam_rgb_srv.py +78 -0
  20. hex_zmq_servers/config/cam_berxel.json +18 -0
  21. hex_zmq_servers/config/cam_dummy.json +12 -0
  22. hex_zmq_servers/config/cam_realsense.json +17 -0
  23. hex_zmq_servers/config/cam_rgb.json +28 -0
  24. hex_zmq_servers/config/mujoco_archer_y6.json +37 -0
  25. hex_zmq_servers/config/mujoco_e3_desktop.json +41 -0
  26. hex_zmq_servers/config/robot_dummy.json +153 -0
  27. hex_zmq_servers/config/robot_gello.json +66 -0
  28. hex_zmq_servers/config/robot_hexarm.json +37 -0
  29. hex_zmq_servers/config/zmq_dummy.json +12 -0
  30. hex_zmq_servers/device_base.py +44 -0
  31. hex_zmq_servers/hex_launch.py +489 -0
  32. hex_zmq_servers/mujoco/__init__.py +28 -0
  33. hex_zmq_servers/mujoco/archer_y6/__init__.py +17 -0
  34. hex_zmq_servers/mujoco/archer_y6/model/assets/arm_base_link.STL +0 -0
  35. hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_1.STL +0 -0
  36. hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_2.STL +0 -0
  37. hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_3.STL +0 -0
  38. hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_4.STL +0 -0
  39. hex_zmq_servers/mujoco/archer_y6/model/assets/arm_link_5.STL +0 -0
  40. hex_zmq_servers/mujoco/archer_y6/model/assets/assets.xml +17 -0
  41. hex_zmq_servers/mujoco/archer_y6/model/assets/camera_link.STL +0 -0
  42. hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_base_link.STL +0 -0
  43. hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_left_helper_link.STL +0 -0
  44. hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_left_link_1.STL +0 -0
  45. hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_left_link_2.STL +0 -0
  46. hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_right_helper_link.STL +0 -0
  47. hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_right_link_1.STL +0 -0
  48. hex_zmq_servers/mujoco/archer_y6/model/assets/gripper_right_link_2.STL +0 -0
  49. hex_zmq_servers/mujoco/archer_y6/model/assets/table_link.STL +0 -0
  50. hex_zmq_servers/mujoco/archer_y6/model/robot.xml +95 -0
  51. hex_zmq_servers/mujoco/archer_y6/model/scene.xml +51 -0
  52. hex_zmq_servers/mujoco/archer_y6/model/setting.xml +37 -0
  53. hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6.py +325 -0
  54. hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6_cli.py +71 -0
  55. hex_zmq_servers/mujoco/archer_y6/mujoco_archer_y6_srv.py +148 -0
  56. hex_zmq_servers/mujoco/e3_desktop/__init__.py +17 -0
  57. hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_base_link.STL +0 -0
  58. hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_1.STL +0 -0
  59. hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_2.STL +0 -0
  60. hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_3.STL +0 -0
  61. hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_4.STL +0 -0
  62. hex_zmq_servers/mujoco/e3_desktop/model/assets/arm_link_5.STL +0 -0
  63. hex_zmq_servers/mujoco/e3_desktop/model/assets/assets.xml +18 -0
  64. hex_zmq_servers/mujoco/e3_desktop/model/assets/camera_link.STL +0 -0
  65. hex_zmq_servers/mujoco/e3_desktop/model/assets/e3_desktop_base_link.STL +0 -0
  66. hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_base_link.STL +0 -0
  67. hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_left_helper_link.STL +0 -0
  68. hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_left_link_1.STL +0 -0
  69. hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_left_link_2.STL +0 -0
  70. hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_right_helper_link.STL +0 -0
  71. hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_right_link_1.STL +0 -0
  72. hex_zmq_servers/mujoco/e3_desktop/model/assets/gripper_right_link_2.STL +0 -0
  73. hex_zmq_servers/mujoco/e3_desktop/model/assets/table_link.STL +0 -0
  74. hex_zmq_servers/mujoco/e3_desktop/model/robot.xml +188 -0
  75. hex_zmq_servers/mujoco/e3_desktop/model/scene.xml +53 -0
  76. hex_zmq_servers/mujoco/e3_desktop/model/setting.xml +72 -0
  77. hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop.py +449 -0
  78. hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop_cli.py +289 -0
  79. hex_zmq_servers/mujoco/e3_desktop/mujoco_e3_desktop_srv.py +244 -0
  80. hex_zmq_servers/mujoco/mujoco_base.py +425 -0
  81. hex_zmq_servers/robot/__init__.py +37 -0
  82. hex_zmq_servers/robot/dummy/__init__.py +17 -0
  83. hex_zmq_servers/robot/dummy/robot_dummy.py +94 -0
  84. hex_zmq_servers/robot/dummy/robot_dummy_cli.py +29 -0
  85. hex_zmq_servers/robot/dummy/robot_dummy_srv.py +82 -0
  86. hex_zmq_servers/robot/gello/__init__.py +17 -0
  87. hex_zmq_servers/robot/gello/robot_gello.py +366 -0
  88. hex_zmq_servers/robot/gello/robot_gello_cli.py +29 -0
  89. hex_zmq_servers/robot/gello/robot_gello_srv.py +93 -0
  90. hex_zmq_servers/robot/hexarm/__init__.py +47 -0
  91. hex_zmq_servers/robot/hexarm/robot_hexarm.py +292 -0
  92. hex_zmq_servers/robot/hexarm/robot_hexarm_cli.py +37 -0
  93. hex_zmq_servers/robot/hexarm/robot_hexarm_srv.py +87 -0
  94. hex_zmq_servers/robot/hexarm/urdf/archer_l6y/empty.urdf +206 -0
  95. hex_zmq_servers/robot/hexarm/urdf/archer_l6y/gp100.urdf +206 -0
  96. hex_zmq_servers/robot/hexarm/urdf/archer_l6y/gp100_handle.urdf +206 -0
  97. hex_zmq_servers/robot/hexarm/urdf/archer_l6y/gp100_p050.urdf +206 -0
  98. hex_zmq_servers/robot/hexarm/urdf/archer_l6y/gp100_p050_handle.urdf +206 -0
  99. hex_zmq_servers/robot/hexarm/urdf/archer_y6/empty.urdf +207 -0
  100. hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100.urdf +207 -0
  101. hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100_handle.urdf +207 -0
  102. hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100_p050.urdf +207 -0
  103. hex_zmq_servers/robot/hexarm/urdf/archer_y6/gp100_p050_handle.urdf +207 -0
  104. hex_zmq_servers/robot/robot_base.py +276 -0
  105. hex_zmq_servers/zmq_base.py +547 -0
  106. hex_zmq_servers-0.3.9.dist-info/METADATA +147 -0
  107. hex_zmq_servers-0.3.9.dist-info/RECORD +110 -0
  108. hex_zmq_servers-0.3.9.dist-info/WHEEL +5 -0
  109. hex_zmq_servers-0.3.9.dist-info/licenses/LICENSE +201 -0
  110. hex_zmq_servers-0.3.9.dist-info/top_level.txt +1 -0
@@ -0,0 +1,173 @@
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-15
7
+ ################################################################
8
+
9
+ from .hex_launch import HexLaunch, HexNodeConfig, HEX_LOG_LEVEL, hex_dict_str, hex_log, hex_err
10
+
11
+ from .device_base import HexDeviceBase
12
+ from .zmq_base import hex_zmq_ts_to_ns, ns_to_hex_zmq_ts, hex_ns_now, hex_zmq_ts_now, hex_zmq_ts_delta_ms
13
+ from .zmq_base import HexRate, HexZMQClientBase, HexZMQServerBase, hex_server_helper
14
+ from .zmq_base import HexZMQDummyClient, HexZMQDummyServer
15
+
16
+ from .robot import HexRobotBase, HexRobotClientBase, HexRobotServerBase
17
+ from .robot import HexRobotDummy, HexRobotDummyClient, HexRobotDummyServer
18
+ from .robot import HexRobotGello, HexRobotGelloClient, HexRobotGelloServer
19
+ from .robot import HexRobotHexarm, HexRobotHexarmClient, HexRobotHexarmServer, HEXARM_URDF_PATH_DICT
20
+
21
+ from .cam import HexCamBase, HexCamClientBase, HexCamServerBase
22
+ from .cam import HexCamDummy, HexCamDummyClient, HexCamDummyServer
23
+ from .cam import HexCamRGB, HexCamRGBClient, HexCamRGBServer
24
+
25
+ import os
26
+
27
+ file_dir = os.path.dirname(os.path.abspath(__file__))
28
+ HEX_ZMQ_SERVERS_PATH_DICT = {
29
+ "zmq_dummy": f"{file_dir}/zmq_base.py",
30
+ "robot_dummy": f"{file_dir}/robot/dummy/robot_dummy_srv.py",
31
+ "robot_gello": f"{file_dir}/robot/gello/robot_gello_srv.py",
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",
35
+ }
36
+ HEX_ZMQ_CONFIGS_PATH_DICT = {
37
+ "zmq_dummy": f"{file_dir}/config/zmq_dummy.json",
38
+ "robot_dummy": f"{file_dir}/config/robot_dummy.json",
39
+ "robot_gello": f"{file_dir}/config/robot_gello.json",
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",
43
+ }
44
+
45
+ __all__ = [
46
+ # version
47
+ "__version__",
48
+
49
+ # path
50
+ "HEX_ZMQ_SERVERS_PATH_DICT",
51
+ "HEX_ZMQ_CONFIGS_PATH_DICT",
52
+ "HEXARM_URDF_PATH_DICT",
53
+
54
+ # launch
55
+ "HexLaunch",
56
+ "HexNodeConfig",
57
+ "HEX_LOG_LEVEL",
58
+ "hex_dict_str",
59
+ "hex_log",
60
+ "hex_err",
61
+
62
+ # base
63
+ "HexDeviceBase",
64
+ "HexRate",
65
+ "hex_zmq_ts_to_ns",
66
+ "ns_to_hex_zmq_ts",
67
+ "hex_ns_now",
68
+ "hex_zmq_ts_now",
69
+ "hex_zmq_ts_delta_ms",
70
+ "HexZMQClientBase",
71
+ "HexZMQServerBase",
72
+ "hex_server_helper",
73
+ "HexZMQDummyClient",
74
+ "HexZMQDummyServer",
75
+
76
+ # robot
77
+ "HexRobotBase",
78
+ "HexRobotClientBase",
79
+ "HexRobotServerBase",
80
+ "HexRobotDummy",
81
+ "HexRobotDummyClient",
82
+ "HexRobotDummyServer",
83
+ "HexRobotGello",
84
+ "HexRobotGelloClient",
85
+ "HexRobotGelloServer",
86
+ "HexRobotHexarm",
87
+ "HexRobotHexarmClient",
88
+ "HexRobotHexarmServer",
89
+
90
+ # camera
91
+ "HexCamBase",
92
+ "HexCamClientBase",
93
+ "HexCamServerBase",
94
+ "HexCamDummy",
95
+ "HexCamDummyClient",
96
+ "HexCamDummyServer",
97
+ "HexCamRGB",
98
+ "HexCamRGBClient",
99
+ "HexCamRGBServer",
100
+ ]
101
+
102
+ # Check optional dependencies availability
103
+ from importlib.util import find_spec
104
+
105
+ _HAS_BERXEL = find_spec("berxel_py_wrapper") is not None
106
+ _HAS_REALSENSE = find_spec("pyrealsense2") is not None
107
+ _HAS_MUJOCO = find_spec("mujoco") is not None
108
+
109
+ # Optional: berxel
110
+ if _HAS_BERXEL:
111
+ from .cam import HexCamBerxel, HexCamBerxelClient, HexCamBerxelServer
112
+ HEX_ZMQ_SERVERS_PATH_DICT.update({
113
+ "cam_berxel":
114
+ f"{file_dir}/cam/berxel/cam_berxel_srv.py",
115
+ })
116
+ HEX_ZMQ_CONFIGS_PATH_DICT.update({
117
+ "cam_berxel":
118
+ f"{file_dir}/config/cam_berxel.json",
119
+ })
120
+ __all__.extend([
121
+ "HexCamBerxel",
122
+ "HexCamBerxelClient",
123
+ "HexCamBerxelServer",
124
+ ])
125
+
126
+ # Optional: realsense
127
+ if _HAS_REALSENSE:
128
+ from .cam import HexCamRealsense, HexCamRealsenseClient, HexCamRealsenseServer
129
+ HEX_ZMQ_SERVERS_PATH_DICT.update({
130
+ "cam_realsense":
131
+ f"{file_dir}/cam/realsense/cam_realsense_srv.py",
132
+ })
133
+ HEX_ZMQ_CONFIGS_PATH_DICT.update({
134
+ "cam_realsense":
135
+ f"{file_dir}/config/cam_realsense.json",
136
+ })
137
+ __all__.extend([
138
+ "HexCamRealsense",
139
+ "HexCamRealsenseClient",
140
+ "HexCamRealsenseServer",
141
+ ])
142
+
143
+ # Optional: mujoco
144
+ if _HAS_MUJOCO:
145
+ from .mujoco import HexMujocoBase, HexMujocoClientBase, HexMujocoServerBase
146
+ from .mujoco import HexMujocoArcherY6, HexMujocoArcherY6Client, HexMujocoArcherY6Server
147
+ from .mujoco import HexMujocoE3Desktop, HexMujocoE3DesktopClient, HexMujocoE3DesktopServer
148
+ HEX_ZMQ_SERVERS_PATH_DICT.update({
149
+ "mujoco_archer_y6":
150
+ f"{file_dir}/mujoco/archer_y6/mujoco_archer_y6_srv.py",
151
+ "mujoco_e3_desktop":
152
+ f"{file_dir}/mujoco/e3_desktop/mujoco_e3_desktop_srv.py",
153
+ })
154
+ HEX_ZMQ_CONFIGS_PATH_DICT.update({
155
+ "mujoco_archer_y6":
156
+ f"{file_dir}/config/mujoco_archer_y6.json",
157
+ "mujoco_e3_desktop":
158
+ f"{file_dir}/config/mujoco_e3_desktop.json",
159
+ })
160
+ __all__.extend([
161
+ # mujoco
162
+ "HexMujocoBase",
163
+ "HexMujocoClientBase",
164
+ "HexMujocoServerBase",
165
+ "HexMujocoArcherY6",
166
+ "HexMujocoArcherY6Client",
167
+ "HexMujocoArcherY6Server",
168
+ "HexMujocoE3Desktop",
169
+ "HexMujocoE3DesktopClient",
170
+ "HexMujocoE3DesktopServer",
171
+ ])
172
+
173
+ # print("#### Thanks for using hex_zmq_servers :D ####")
@@ -0,0 +1,52 @@
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 HexCamBase, HexCamClientBase, HexCamServerBase
10
+ from .dummy import HexCamDummy, HexCamDummyClient, HexCamDummyServer
11
+ from .rgb import HexCamRGB, HexCamRGBClient, HexCamRGBServer
12
+
13
+ __all__ = [
14
+ # base
15
+ "HexCamBase",
16
+ "HexCamClientBase",
17
+ "HexCamServerBase",
18
+
19
+ # dummy
20
+ "HexCamDummy",
21
+ "HexCamDummyClient",
22
+ "HexCamDummyServer",
23
+
24
+ # rgb
25
+ "HexCamRGB",
26
+ "HexCamRGBClient",
27
+ "HexCamRGBServer",
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_berxel import HexCamBerxel
10
+ from .cam_berxel_cli import HexCamBerxelClient
11
+ from .cam_berxel_srv import HexCamBerxelServer
12
+
13
+ __all__ = [
14
+ "HexCamBerxel",
15
+ "HexCamBerxelClient",
16
+ "HexCamBerxelServer",
17
+ ]
@@ -0,0 +1,282 @@
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
+ from collections import deque
13
+
14
+ from ..cam_base import HexCamBase
15
+ from ...zmq_base import hex_ns_now, hex_zmq_ts_now
16
+ from ...hex_launch import hex_log, HEX_LOG_LEVEL
17
+ from berxel_py_wrapper import *
18
+
19
+ CAMERA_CONFIG = {
20
+ "serial_number": 'P100RYB4C03M2B322',
21
+ "exposure": 10000,
22
+ "gain": 100,
23
+ "frame_rate": 30,
24
+ "sens_ts": True,
25
+ }
26
+
27
+
28
+ class HexCamBerxel(HexCamBase):
29
+
30
+ def __init__(
31
+ self,
32
+ camera_config: dict = CAMERA_CONFIG,
33
+ realtime_mode: bool = False,
34
+ ):
35
+ HexCamBase.__init__(self, realtime_mode)
36
+
37
+ try:
38
+ self.__serial_number = camera_config["serial_number"]
39
+ self.__exposure = camera_config["exposure"]
40
+ self.__gain = camera_config["gain"]
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
+ # berxel variables
50
+ self.__context = None
51
+ self.__device = None
52
+ # camera variables
53
+ self.__intri = np.zeros(4)
54
+
55
+ # open device
56
+ if not self.__open_device(self.__serial_number):
57
+ print("open device failed")
58
+ return
59
+
60
+ # start stream
61
+ if not self.__start_stream():
62
+ print("start stream failed")
63
+ return
64
+
65
+ # start work loop
66
+ self._working.set()
67
+
68
+ def get_intri(self) -> np.ndarray:
69
+ self._wait_for_working()
70
+ return self.__intri
71
+
72
+ def get_serial_number(self) -> np.ndarray:
73
+ self._wait_for_working()
74
+ return self.__serial_number
75
+
76
+ def work_loop(self, hex_queues: list[deque | threading.Event]):
77
+ rgb_queue = hex_queues[0]
78
+ depth_queue = hex_queues[1]
79
+ stop_event = hex_queues[2]
80
+
81
+ # clean cache
82
+ clean_cnt = 0
83
+ while clean_cnt < 5:
84
+ hawk_rgb_frame = self.__device.readColorFrame(40)
85
+ hawk_depth_frame = self.__device.readDepthFrame(40)
86
+ if hawk_rgb_frame is not None:
87
+ self.__device.releaseFrame(hawk_rgb_frame)
88
+ if hawk_depth_frame is not None:
89
+ self.__device.releaseFrame(hawk_depth_frame)
90
+ clean_cnt += 1
91
+ time.sleep(0.01)
92
+
93
+ rgb_count = 0
94
+ depth_count = 0
95
+ bias_ns = hex_ns_now() - time.time_ns()
96
+ while self._working.is_set() and not stop_event.is_set():
97
+ # read frame
98
+ hawk_rgb_frame = self.__device.readColorFrame(40)
99
+ hawk_depth_frame = self.__device.readDepthFrame(40)
100
+
101
+ # collect rgb frame
102
+ if hawk_rgb_frame is not None:
103
+ ts, frame = self.__unpack_frame(hawk_rgb_frame, False, bias_ns)
104
+ rgb_queue.append((ts, rgb_count, frame))
105
+ rgb_count = (rgb_count + 1) % self._max_seq_num
106
+
107
+ # collect depth frame
108
+ if hawk_depth_frame is not None:
109
+ ts, frame = self.__unpack_frame(hawk_depth_frame, True,
110
+ bias_ns)
111
+ depth_queue.append((ts, depth_count, frame))
112
+ depth_count = (depth_count + 1) % self._max_seq_num
113
+
114
+ self.__device.releaseFrame(hawk_rgb_frame)
115
+ self.__device.releaseFrame(hawk_depth_frame)
116
+
117
+ # close
118
+ self.close()
119
+
120
+ def __unpack_frame(
121
+ self,
122
+ hawk_frame: BerxelHawkFrame,
123
+ depth: bool = False,
124
+ bias_ns: int = 0,
125
+ ):
126
+ # common variables
127
+ berxel_ts_ns = bias_ns + int(hawk_frame.getTimeStamp() * 1_000)
128
+ ts = {
129
+ "s": berxel_ts_ns // 1_000_000_000,
130
+ "ns": berxel_ts_ns % 1_000_000_000,
131
+ }
132
+ width = hawk_frame.getWidth()
133
+ height = hawk_frame.getHeight()
134
+
135
+ if depth:
136
+ # depth frame
137
+ frame_buffer = hawk_frame.getDataAsUint16()
138
+ frame = np.ndarray(
139
+ shape=(height, width),
140
+ dtype=np.uint16,
141
+ buffer=frame_buffer,
142
+ )
143
+ pixel_type = hawk_frame.getPixelType()
144
+ if pixel_type == BerxelHawkPixelType.forward_dict[
145
+ 'BERXEL_HAWK_PIXEL_TYPE_DEP_16BIT_12I_4D']:
146
+ frame = frame // 16
147
+ elif pixel_type == BerxelHawkPixelType.forward_dict[
148
+ 'BERXEL_HAWK_PIXEL_TYPE_DEP_16BIT_13I_3D']:
149
+ frame = frame // 8
150
+ else:
151
+ raise ValueError(f"pixel_type: {pixel_type} not supported")
152
+ else:
153
+ # rgb frame
154
+ frame_buffer = hawk_frame.getDataAsUint8()
155
+ frame = np.ndarray(
156
+ shape=(height, width, 3),
157
+ dtype=np.uint8,
158
+ buffer=frame_buffer,
159
+ )
160
+ frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
161
+
162
+ return ts if self.__sens_ts else hex_zmq_ts_now(), frame
163
+
164
+ def __open_device(self, serial_number: str | None = None) -> bool:
165
+ # init context
166
+ self.__context = BerxelHawkContext()
167
+ if self.__context is None:
168
+ print("init failed")
169
+ return False
170
+ self.__context.initCamera()
171
+
172
+ # open device
173
+ device_list = self.__context.getDeviceList()
174
+ if len(device_list) < 1:
175
+ print("can not find device")
176
+ return False
177
+ if serial_number is not None:
178
+ device_idx = -1
179
+
180
+ # check serial number
181
+ def same_serial(tar_serial, device_serial):
182
+
183
+ def norm_serial(x):
184
+ if x is None:
185
+ return None
186
+ if isinstance(x, (bytes, bytearray)):
187
+ x = x.decode('utf-8', 'ignore')
188
+ x = x.replace('\x00', '').strip()
189
+ return x.upper()
190
+
191
+ return norm_serial(tar_serial) == norm_serial(device_serial)
192
+
193
+ for idx, device in enumerate(device_list):
194
+ if same_serial(serial_number, device.serialNumber):
195
+ print(f"find device with serial number: {serial_number}")
196
+ device_idx = idx
197
+ break
198
+ if device_idx == -1:
199
+ print(
200
+ f"can not find device with serial number: {serial_number}")
201
+ print("available device serial numbers:")
202
+ for device in device_list:
203
+ print(f"{device.serialNumber}")
204
+ return False
205
+ self.__device = self.__context.openDevice(device_list[device_idx])
206
+ else:
207
+ print("No serial number, use first device")
208
+ self.__device = self.__context.openDevice(device_list[0])
209
+
210
+ if self.__device is None:
211
+ print("open device failed")
212
+ return False
213
+
214
+ return True
215
+
216
+ def __start_stream(self):
217
+ self.__device.setColorExposureGain(self.__exposure, self.__gain)
218
+ self.__device.setRegistrationEnable(True)
219
+ self.__device.setFrameSync(True)
220
+ while self.__device.setSystemClock() != 0:
221
+ print("set system clock failed")
222
+ time.sleep(0.1)
223
+
224
+ intrinsic_params = self.__device.getDeviceIntriscParams()
225
+ self.__intri[0] = intrinsic_params.colorIntrinsicParams.fx / 2
226
+ self.__intri[1] = intrinsic_params.colorIntrinsicParams.fy / 2
227
+ self.__intri[2] = intrinsic_params.colorIntrinsicParams.cx / 2
228
+ self.__intri[3] = intrinsic_params.colorIntrinsicParams.cy / 2
229
+
230
+ color_frame_mode = self.__device.getCurrentFrameMode(
231
+ BerxelHawkStreamType.forward_dict['BERXEL_HAWK_COLOR_STREAM'])
232
+ depth_frame_mode = self.__device.getCurrentFrameMode(
233
+ BerxelHawkStreamType.forward_dict['BERXEL_HAWK_DEPTH_STREAM'])
234
+ color_frame_mode.framerate = self.__frame_rate
235
+ depth_frame_mode.framerate = self.__frame_rate
236
+ self.__device.setFrameMode(
237
+ BerxelHawkStreamType.forward_dict['BERXEL_HAWK_COLOR_STREAM'],
238
+ color_frame_mode)
239
+ self.__device.setFrameMode(
240
+ BerxelHawkStreamType.forward_dict['BERXEL_HAWK_DEPTH_STREAM'],
241
+ depth_frame_mode)
242
+ ret = self.__device.startStreams(
243
+ BerxelHawkStreamType.forward_dict['BERXEL_HAWK_DEPTH_STREAM']
244
+ | BerxelHawkStreamType.forward_dict['BERXEL_HAWK_COLOR_STREAM'])
245
+ if ret == 0:
246
+ print("start stream succeed")
247
+ return True
248
+ else:
249
+ print("start stream failed")
250
+ return False
251
+
252
+ def close(self):
253
+ if not self._working.is_set():
254
+ return
255
+ self._working.clear()
256
+ self.__stop_stream()
257
+ self.__close_device()
258
+ hex_log(HEX_LOG_LEVEL["info"], "HexCamBerxel closed")
259
+
260
+ def __stop_stream(self):
261
+ if self.__device is None:
262
+ return False
263
+ ret = self.__device.stopStream(
264
+ BerxelHawkStreamType.forward_dict['BERXEL_HAWK_DEPTH_STREAM']
265
+ | BerxelHawkStreamType.forward_dict['BERXEL_HAWK_COLOR_STREAM'])
266
+ if ret == 0:
267
+ return True
268
+ else:
269
+ return False
270
+
271
+ def __close_device(self):
272
+ if self.__context is None:
273
+ return
274
+ if self.__device is None:
275
+ return
276
+
277
+ ret = self.__context.closeDevice(self.__device)
278
+ if ret == 0:
279
+ print("clsoe device succeed")
280
+ else:
281
+ print("close device Failed")
282
+ self.__context.destroyCamera()
@@ -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 HexCamBerxelClient(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,79 @@
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_berxel import HexCamBerxel
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.berxel.cam_berxel import HexCamBerxel
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": 'P100RYB4C03M2B322',
36
+ "exposure": 10000,
37
+ "gain": 100,
38
+ "frame_rate": 30,
39
+ "sens_ts": True,
40
+ }
41
+
42
+
43
+ class HexCamBerxelServer(HexCamServerBase):
44
+
45
+ def __init__(
46
+ self,
47
+ net_config: dict = NET_CONFIG,
48
+ params_config: dict = CAMERA_CONFIG,
49
+ ):
50
+ HexCamServerBase.__init__(self, net_config)
51
+
52
+ # camera
53
+ self._device = HexCamBerxel(params_config,
54
+ net_config.get("realtime_mode", False))
55
+
56
+ def _process_request(self, recv_hdr: dict, recv_buf: np.ndarray):
57
+ if recv_hdr["cmd"] == "is_working":
58
+ return self.no_ts_hdr(recv_hdr, self._device.is_working()), None
59
+ elif recv_hdr["cmd"] == "get_intri":
60
+ intri = self._device.get_intri()
61
+ return self.no_ts_hdr(recv_hdr, intri is not None), intri
62
+ elif recv_hdr["cmd"] == "get_rgb":
63
+ return self._get_frame(recv_hdr, False)
64
+ elif recv_hdr["cmd"] == "get_depth":
65
+ return self._get_frame(recv_hdr, True)
66
+ else:
67
+ raise ValueError(f"unknown command: {recv_hdr['cmd']}")
68
+
69
+
70
+ if __name__ == "__main__":
71
+ import argparse, json
72
+ from hex_zmq_servers.zmq_base import hex_server_helper
73
+
74
+ parser = argparse.ArgumentParser()
75
+ parser.add_argument("--cfg", type=str, required=True)
76
+ args = parser.parse_args()
77
+ cfg = json.loads(args.cfg)
78
+
79
+ hex_server_helper(cfg, HexCamBerxelServer)