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,292 @@
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
+ from collections import deque
13
+
14
+ from ..robot_base import HexRobotBase
15
+ from ...zmq_base import (
16
+ hex_zmq_ts_now,
17
+ hex_zmq_ts_delta_ms,
18
+ HexRate,
19
+ )
20
+ from ...hex_launch import hex_log, HEX_LOG_LEVEL
21
+ from hex_device import HexDeviceApi, MotorBase
22
+ from hex_device.motor_base import CommandType
23
+
24
+ ROBOT_CONFIG = {
25
+ "device_ip": "172.18.8.161",
26
+ "device_port": 8439,
27
+ "control_hz": 250,
28
+ "arm_type": "archer_y6",
29
+ "use_gripper": True,
30
+ "mit_kp": [200.0, 200.0, 200.0, 75.0, 15.0, 15.0, 20.0],
31
+ "mit_kd": [12.5, 12.5, 12.5, 6.0, 0.31, 0.31, 1.0],
32
+ "sens_ts": True,
33
+ }
34
+
35
+ HEX_DEVICE_TYPE_DICT = {
36
+ "archer_y6": 16,
37
+ "archer_l6y": 17,
38
+ }
39
+
40
+
41
+ class HexRobotHexarm(HexRobotBase):
42
+
43
+ def __init__(
44
+ self,
45
+ robot_config: dict = ROBOT_CONFIG,
46
+ realtime_mode: bool = False,
47
+ ):
48
+ HexRobotBase.__init__(self, realtime_mode)
49
+
50
+ try:
51
+ device_ip = robot_config["device_ip"]
52
+ device_port = robot_config["device_port"]
53
+ control_hz = robot_config["control_hz"]
54
+ arm_type = HEX_DEVICE_TYPE_DICT[robot_config["arm_type"]]
55
+ use_gripper = robot_config["use_gripper"]
56
+ self.__sens_ts = robot_config["sens_ts"]
57
+ except KeyError as ke:
58
+ missing_key = ke.args[0]
59
+ raise ValueError(
60
+ f"robot_config is not valid, missing key: {missing_key}")
61
+
62
+ self.__mit_kp = robot_config.get(
63
+ "mit_kp",
64
+ [200.0, 200.0, 200.0, 75.0, 15.0, 15.0, 20.0],
65
+ )
66
+ self.__mit_kd = robot_config.get(
67
+ "mit_kd",
68
+ [12.5, 12.5, 12.5, 6.0, 0.31, 0.31, 1.0],
69
+ )
70
+
71
+ # variables
72
+ # hex_arm variables
73
+ self.__hex_api: HexDeviceApi | None = None
74
+ self.__arm_archer: MotorBase | None = None
75
+ self.__gripper: MotorBase | None = None
76
+
77
+ # buffer
78
+ self.__arm_state_buffer: dict | None = None
79
+ self.__gripper_state_buffer: dict | None = None
80
+
81
+ # open device
82
+ self.__hex_api = HexDeviceApi(
83
+ ws_url=f"ws://{device_ip}:{device_port}",
84
+ control_hz=control_hz,
85
+ )
86
+
87
+ # open arm
88
+ while self.__hex_api.find_device_by_robot_type(arm_type) is None:
89
+ print("\033[33mArm not found\033[0m")
90
+ time.sleep(1)
91
+ self.__arm_archer = self.__hex_api.find_device_by_robot_type(arm_type)
92
+ self.__arm_archer.start()
93
+ self.__arm_dofs = len(self.__arm_archer)
94
+ self._limits = self.__arm_archer.get_joint_limits()
95
+
96
+ # try to open gripper
97
+ self.__gripper_dofs = 0
98
+ self.__gripper = None
99
+ if use_gripper:
100
+ self.__gripper = self.__hex_api.find_optional_device_by_id(1)
101
+ if self.__gripper is not None:
102
+ self.__gripper_dofs = len(self.__gripper)
103
+ self._limits += [self.__gripper.get_joint_limits()]
104
+ else:
105
+ print("\033[33mGripper not found\033[0m")
106
+
107
+ # modify variables
108
+ self._dofs = [self.__arm_dofs + self.__gripper_dofs]
109
+ self._limits = np.ascontiguousarray(np.asarray(self._limits)).reshape(
110
+ self._dofs[0], 3, 2)
111
+ self.__mit_kp = np.ascontiguousarray(np.asarray(self.__mit_kp))
112
+ self.__mit_kd = np.ascontiguousarray(np.asarray(self.__mit_kd))
113
+ if self.__mit_kp.shape[0] < self._dofs[0] or self.__mit_kd.shape[
114
+ 0] < self._dofs[0]:
115
+ raise ValueError(
116
+ "The length of mit_kp and mit_kd must be greater than or equal to the number of motors"
117
+ )
118
+ elif self.__mit_kp.shape[0] > self._dofs[0] or self.__mit_kd.shape[
119
+ 0] > self._dofs[0]:
120
+ print(
121
+ f"\033[33mThe length of mit_kp and mit_kd is greater than the number of motors\033[0m"
122
+ )
123
+ self.__mit_kp = self.__mit_kp[:self._dofs[0]]
124
+ self.__mit_kd = self.__mit_kd[:self._dofs[0]]
125
+
126
+ # start work loop
127
+ self._working.set()
128
+
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]
133
+
134
+ last_states_ts = hex_zmq_ts_now()
135
+ states_count = 0
136
+ last_cmds_seq = -1
137
+ rate = HexRate(2000)
138
+ while self._working.is_set() and not stop_event.is_set():
139
+ # states
140
+ ts, states = self.__get_states()
141
+ if states is not None:
142
+ if hex_zmq_ts_delta_ms(ts, last_states_ts) > 1e-6:
143
+ last_states_ts = ts
144
+ states_queue.append((ts, states_count, states))
145
+ states_count = (states_count + 1) % self._max_seq_num
146
+
147
+ # cmds
148
+ cmds_pack = None
149
+ try:
150
+ cmds_pack = cmds_queue[
151
+ -1] if self._realtime_mode else cmds_queue.popleft()
152
+ except IndexError:
153
+ pass
154
+ if cmds_pack is not None:
155
+ ts, seq, cmds = cmds_pack
156
+ if seq != last_cmds_seq:
157
+ last_cmds_seq = seq
158
+ if hex_zmq_ts_delta_ms(hex_zmq_ts_now(), ts) < 200.0:
159
+ self.__set_cmds(cmds)
160
+
161
+ # sleep
162
+ rate.sleep()
163
+
164
+ # close
165
+ self.close()
166
+
167
+ def __get_states(self) -> tuple[np.ndarray | None, dict | None]:
168
+ if self.__arm_archer is None:
169
+ return None, None
170
+
171
+ # (arm_dofs, 3) # pos vel eff
172
+ if self.__arm_state_buffer is None:
173
+ self.__arm_state_buffer = self.__arm_archer.get_simple_motor_status(
174
+ )
175
+
176
+ # (gripper_dofs, 3) # pos vel eff
177
+ if self.__gripper is not None and self.__gripper_state_buffer is None:
178
+ self.__gripper_state_buffer = self.__gripper.get_simple_motor_status(
179
+ )
180
+
181
+ arm_ready = self.__arm_state_buffer is not None
182
+ gripper_ready = self.__gripper is None or self.__gripper_state_buffer is not None
183
+ if arm_ready and gripper_ready:
184
+ arm_ts = self.__arm_state_buffer['ts']
185
+ gripper_ts = self.__gripper_state_buffer[
186
+ 'ts'] if self.__gripper is not None else arm_ts
187
+
188
+ delta_ms = hex_zmq_ts_delta_ms(arm_ts, gripper_ts)
189
+ if np.fabs(delta_ms) < 1e-6:
190
+ pos = self.__arm_state_buffer['pos']
191
+ vel = self.__arm_state_buffer['vel']
192
+ eff = self.__arm_state_buffer['eff']
193
+
194
+ if self.__gripper is not None:
195
+ pos = np.concatenate(
196
+ [pos, self.__gripper_state_buffer['pos']])
197
+ vel = np.concatenate(
198
+ [vel, self.__gripper_state_buffer['vel']])
199
+ eff = np.concatenate(
200
+ [eff, self.__gripper_state_buffer['eff']])
201
+
202
+ state = np.array([pos, vel, eff]).T
203
+ self.__arm_state_buffer, self.__gripper_state_buffer = None, None
204
+ return arm_ts if self.__sens_ts else hex_zmq_ts_now(), state
205
+ elif delta_ms > 0.0:
206
+ self.__gripper_state_buffer = None
207
+ return None, None
208
+ else:
209
+ self.__arm_state_buffer = None
210
+ return None, None
211
+
212
+ return None, None
213
+
214
+ def __set_cmds(self, cmds: np.ndarray) -> bool:
215
+ # cmds: (n)
216
+ # [pos_0, ..., pos_n]
217
+ # cmds: (n, 2)
218
+ # [[pos_0, tor_0], ..., [pos_n, tor_n]]
219
+ # cmds: (n, 5)
220
+ # [[pos_0, vel_0, tor_0, kp_0, kd_0], ..., [pos_n, vel_n, tor_n, kp_n, kd_n]]
221
+ if self.__arm_archer is None:
222
+ print("\033[91mArm not found\033[0m")
223
+ return False
224
+
225
+ if cmds.shape[0] < self._dofs[0]:
226
+ print(
227
+ "\033[91mThe length of joint_angles must be greater than or equal to the number of motors\033[0m"
228
+ )
229
+ return False
230
+ elif cmds.shape[0] > self._dofs[0]:
231
+ print(
232
+ f"\033[33mThe length of joint_angles is greater than the number of motors\033[0m"
233
+ )
234
+ cmds = cmds[:self._dofs[0]]
235
+
236
+ cmd_pos = None
237
+ tar_vel = np.zeros(self._dofs[0])
238
+ cmd_tor = np.zeros(self._dofs[0])
239
+ cmd_kp = self.__mit_kp.copy()
240
+ cmd_kd = self.__mit_kd.copy()
241
+ if len(cmds.shape) == 1:
242
+ cmd_pos = cmds
243
+ elif len(cmds.shape) == 2:
244
+ if cmds.shape[1] == 2:
245
+ cmd_pos = cmds[:, 0]
246
+ cmd_tor = cmds[:, 1]
247
+ elif cmds.shape[1] == 5:
248
+ cmd_pos = cmds[:, 0]
249
+ tar_vel = cmds[:, 1]
250
+ cmd_tor = cmds[:, 2]
251
+ cmd_kp = cmds[:, 3]
252
+ cmd_kd = cmds[:, 4]
253
+ else:
254
+ raise ValueError(f"The shape of cmds is invalid: {cmds.shape}")
255
+ else:
256
+ raise ValueError(f"The shape of cmds is invalid: {cmds.shape}")
257
+ tar_pos = self._apply_pos_limits(
258
+ cmd_pos,
259
+ self._limits[:, 0, 0],
260
+ self._limits[:, 0, 1],
261
+ )
262
+
263
+ # arm
264
+ mit_cmd = self.__arm_archer.construct_mit_command(
265
+ tar_pos[:self.__arm_dofs],
266
+ tar_vel[:self.__arm_dofs],
267
+ cmd_tor[:self.__arm_dofs],
268
+ cmd_kp[:self.__arm_dofs],
269
+ cmd_kd[:self.__arm_dofs],
270
+ )
271
+ self.__arm_archer.motor_command(CommandType.MIT, mit_cmd)
272
+
273
+ # gripper
274
+ if self.__gripper is not None:
275
+ mit_cmd = self.__gripper.construct_mit_command(
276
+ tar_pos[self.__arm_dofs:],
277
+ tar_vel[self.__arm_dofs:],
278
+ cmd_tor[self.__arm_dofs:],
279
+ cmd_kp[self.__arm_dofs:],
280
+ cmd_kd[self.__arm_dofs:],
281
+ )
282
+ self.__gripper.motor_command(CommandType.MIT, mit_cmd)
283
+
284
+ return True
285
+
286
+ def close(self):
287
+ if not self._working.is_set():
288
+ return
289
+ self._working.clear()
290
+ self.__arm_archer.stop()
291
+ self.__hex_api.close()
292
+ hex_log(HEX_LOG_LEVEL["info"], "HexRobotHexarm closed")
@@ -0,0 +1,37 @@
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
+ from ..robot_base import HexRobotClientBase
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
+ ROBOT_CONFIG = {
22
+ "device_ip": "172.18.8.161",
23
+ "device_port": 8439,
24
+ "control_hz": 250,
25
+ "arm_type": "archer_l6y",
26
+ "sens_ts": True,
27
+ }
28
+
29
+
30
+ class HexRobotHexarmClient(HexRobotClientBase):
31
+
32
+ def __init__(
33
+ self,
34
+ net_config: dict = NET_CONFIG,
35
+ ):
36
+ HexRobotClientBase.__init__(self, net_config)
37
+ self._wait_for_working()
@@ -0,0 +1,87 @@
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 numpy as np
10
+
11
+ try:
12
+ from ..robot_base import HexRobotServerBase
13
+ from .robot_hexarm import HexRobotHexarm
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.robot.robot_base import HexRobotServerBase
22
+ from hex_zmq_servers.robot.hexarm.robot_hexarm import HexRobotHexarm
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
+ ROBOT_CONFIG = {
35
+ "device_ip": "172.18.8.161",
36
+ "device_port": 8439,
37
+ "control_hz": 250,
38
+ "arm_type": "archer_l6y",
39
+ "use_gripper": True,
40
+ "mit_kp": [200.0, 200.0, 200.0, 75.0, 15.0, 15.0, 0.0],
41
+ "mit_kd": [12.5, 12.5, 12.5, 6.0, 0.31, 0.31, 0.0],
42
+ "sens_ts": True,
43
+ }
44
+
45
+
46
+ class HexRobotHexarmServer(HexRobotServerBase):
47
+
48
+ def __init__(
49
+ self,
50
+ net_config: dict = NET_CONFIG,
51
+ params_config: dict = ROBOT_CONFIG,
52
+ ):
53
+ HexRobotServerBase.__init__(self, net_config)
54
+
55
+ # robot
56
+ self._device = HexRobotHexarm(params_config,
57
+ net_config.get("realtime_mode", False))
58
+
59
+ def _process_request(self, recv_hdr: dict, recv_buf: np.ndarray):
60
+ if recv_hdr["cmd"] == "is_working":
61
+ return self.no_ts_hdr(recv_hdr, self._device.is_working()), None
62
+ elif recv_hdr["cmd"] == "seq_clear":
63
+ return self.no_ts_hdr(recv_hdr, self._seq_clear()), None
64
+ elif recv_hdr["cmd"] == "get_dofs":
65
+ dofs = self._device.get_dofs()
66
+ return self.no_ts_hdr(recv_hdr, dofs is not None), dofs
67
+ elif recv_hdr["cmd"] == "get_limits":
68
+ limits = self._device.get_limits()
69
+ return self.no_ts_hdr(recv_hdr, limits is not None), limits
70
+ elif recv_hdr["cmd"] == "get_states":
71
+ return self._get_states(recv_hdr)
72
+ elif recv_hdr["cmd"] == "set_cmds":
73
+ return self._set_cmds(recv_hdr, recv_buf)
74
+ else:
75
+ raise ValueError(f"unknown command: {recv_hdr['cmd']}")
76
+
77
+
78
+ if __name__ == "__main__":
79
+ import argparse, json
80
+ from hex_zmq_servers.zmq_base import hex_server_helper
81
+
82
+ parser = argparse.ArgumentParser()
83
+ parser.add_argument("--cfg", type=str, required=True)
84
+ args = parser.parse_args()
85
+ cfg = json.loads(args.cfg)
86
+
87
+ hex_server_helper(cfg, HexRobotHexarmServer)
@@ -0,0 +1,206 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <robot name="archer_l6y">
3
+ <link name="base_link">
4
+ <inertial>
5
+ <origin xyz="-0.00080975 0.00005863 0.05684460" rpy="0 0 0" />
6
+ <mass value="0.61800543" />
7
+ <inertia ixx="0.00055618" ixy="-0.00000009" ixz="-0.00000663" iyy="0.00058624" iyz="0.00000086" izz="0.00060508" />
8
+ </inertial>
9
+ <visual>
10
+ <origin xyz="0 0 0" rpy="0 0 0" />
11
+ <geometry>
12
+ <mesh filename="package://xpkg_urdf_archer_l6y/meshes/base_link.STL" />
13
+ </geometry>
14
+ <material name="">
15
+ <color rgba="1 1 1 1" />
16
+ </material>
17
+ </visual>
18
+ <collision>
19
+ <origin xyz="0 0 0" rpy="0 0 0" />
20
+ <geometry>
21
+ <mesh filename="package://xpkg_urdf_archer_l6y/meshes/base_link.STL" />
22
+ </geometry>
23
+ </collision>
24
+ </link>
25
+
26
+ <link name="link_1">
27
+ <inertial>
28
+ <origin xyz="0.00884023 -0.00039740 0.03457242" rpy="0 0 0" />
29
+ <mass value="0.29593000" />
30
+ <inertia ixx="0.00047871" ixy="0.00000088" ixz="-0.00005799" iyy="0.00030053" iyz="0.00000258" izz="0.00041726" />
31
+ </inertial>
32
+ <visual>
33
+ <origin xyz="0 0 0" rpy="0 0 0" />
34
+ <geometry>
35
+ <mesh filename="package://xpkg_urdf_archer_l6y/meshes/link_1.STL" />
36
+ </geometry>
37
+ <material name="">
38
+ <color rgba="1 1 1 1" />
39
+ </material>
40
+ </visual>
41
+ <collision>
42
+ <origin xyz="0 0 0" rpy="0 0 0" />
43
+ <geometry>
44
+ <mesh filename="package://xpkg_urdf_archer_l6y/meshes/link_1.STL" />
45
+ </geometry>
46
+ </collision>
47
+ </link>
48
+ <joint name="joint_1" type="revolute">
49
+ <origin xyz="0 0 0.08355" rpy="0 0 0" />
50
+ <parent link="base_link" />
51
+ <child link="link_1" />
52
+ <axis xyz="0 0 1" />
53
+ <limit lower="-2.8623" upper="2.8623" effort="1" velocity="1" />
54
+ </joint>
55
+
56
+ <link name="link_2">
57
+ <inertial>
58
+ <origin xyz="-0.00159885 0.02740310 0.13379837" rpy="0 0 0" />
59
+ <mass value="1.34359000" />
60
+ <inertia ixx="0.01905633" ixy="0.00000078" ixz="0.00001635" iyy="0.01890424" iyz="0.00000765" izz="0.00086433" />
61
+ </inertial>
62
+ <visual>
63
+ <origin xyz="0 0 0" rpy="0 0 0" />
64
+ <geometry>
65
+ <mesh filename="package://xpkg_urdf_archer_l6y/meshes/link_2.STL" />
66
+ </geometry>
67
+ <material name="">
68
+ <color rgba="1 1 1 1" />
69
+ </material>
70
+ </visual>
71
+ <collision>
72
+ <origin xyz="0 0 0" rpy="0 0 0" />
73
+ <geometry>
74
+ <mesh filename="package://xpkg_urdf_archer_l6y/meshes/link_2.STL" />
75
+ </geometry>
76
+ </collision>
77
+ </link>
78
+ <joint name="joint_2" type="revolute">
79
+ <origin xyz="0.02 -0.0285 0.0555" rpy="0 0 0" />
80
+ <parent link="link_1" />
81
+ <child link="link_2" />
82
+ <axis xyz="0 1 0" />
83
+ <limit lower="-2.0943" upper="1.5707" effort="1" velocity="1" />
84
+ </joint>
85
+
86
+ <link name="link_3">
87
+ <inertial>
88
+ <origin xyz="-0.05454198 0.02770576 0.14631127" rpy="0 0 0" />
89
+ <mass value="1.08626000" />
90
+ <inertia ixx="0.01172853" ixy="-0.00000662" ixz="0.00163495" iyy="0.01182587" iyz="0.00007450" izz="0.00147592" />
91
+ </inertial>
92
+ <visual>
93
+ <origin xyz="0 0 0" rpy="0 0 0" />
94
+ <geometry>
95
+ <mesh filename="package://xpkg_urdf_archer_l6y/meshes/link_3.STL" />
96
+ </geometry>
97
+ <material name="">
98
+ <color rgba="1 1 1 1" />
99
+ </material>
100
+ </visual>
101
+ <collision>
102
+ <origin xyz="0 0 0" rpy="0 0 0" />
103
+ <geometry>
104
+ <mesh filename="package://xpkg_urdf_archer_l6y/meshes/link_3.STL" />
105
+ </geometry>
106
+ </collision>
107
+ </link>
108
+ <joint name="joint_3" type="revolute">
109
+ <origin xyz="0 0 0.27" rpy="0 0 0" />
110
+ <parent link="link_2" />
111
+ <child link="link_3" />
112
+ <axis xyz="0 1 0" />
113
+ <limit lower="0" upper="3.159" effort="1" velocity="1" />
114
+ </joint>
115
+
116
+ <link name="link_4">
117
+ <inertial>
118
+ <origin xyz="-0.04639218 0.02832840 0.04493954" rpy="0 0 0" />
119
+ <mass value="0.53458000" />
120
+ <inertia ixx="0.00085129" ixy="0.00000633" ixz="0.00043133" iyy="0.00109396" iyz="-0.00000547" izz="0.00087351" />
121
+ </inertial>
122
+ <visual>
123
+ <origin xyz="0 0 0" rpy="0 0 0" />
124
+ <geometry>
125
+ <mesh filename="package://xpkg_urdf_archer_l6y/meshes/link_4.STL" />
126
+ </geometry>
127
+ <material name="">
128
+ <color rgba="1 1 1 1" />
129
+ </material>
130
+ </visual>
131
+ <collision>
132
+ <origin xyz="0 0 0" rpy="0 0 0" />
133
+ <geometry>
134
+ <mesh filename="package://xpkg_urdf_archer_l6y/meshes/link_4.STL" />
135
+ </geometry>
136
+ </collision>
137
+ </link>
138
+ <joint name="joint_4" type="revolute">
139
+ <origin xyz="-0.065 -5E-05 0.25" rpy="0 0 0" />
140
+ <parent link="link_3" />
141
+ <child link="link_4" />
142
+ <axis xyz="0 1 0" />
143
+ <limit lower="-1.5707" upper="1.5707" effort="1" velocity="1" />
144
+ </joint>
145
+
146
+ <link name="link_5">
147
+ <inertial>
148
+ <origin xyz="0.04082486 0.00006149 0.00717093" rpy="0 0 0" />
149
+ <mass value="0.38996000" />
150
+ <inertia ixx="0.00016500" ixy="-0.00000021" ixz="-0.00002287" iyy="0.00022995" iyz="0.00000039" izz="0.00021724" />
151
+ </inertial>
152
+ <visual>
153
+ <origin xyz="0 0 0" rpy="0 0 0" />
154
+ <geometry>
155
+ <mesh filename="package://xpkg_urdf_archer_l6y/meshes/link_5.STL" />
156
+ </geometry>
157
+ <material name="">
158
+ <color rgba="1 1 1 1" />
159
+ </material>
160
+ </visual>
161
+ <collision>
162
+ <origin xyz="0 0 0" rpy="0 0 0" />
163
+ <geometry>
164
+ <mesh filename="package://xpkg_urdf_archer_l6y/meshes/link_5.STL" />
165
+ </geometry>
166
+ </collision>
167
+ </link>
168
+ <joint name="joint_5" type="revolute">
169
+ <origin xyz="-0.046 0.0285 0.065" rpy="0 0 0" />
170
+ <parent link="link_4" />
171
+ <child link="link_5" />
172
+ <axis xyz="-1 0 0" />
173
+ <limit lower="-1.5707" upper="1.5707" effort="1" velocity="1" />
174
+ </joint>
175
+
176
+ <link name="link_6">
177
+ <inertial>
178
+ <origin xyz="0 0 0" rpy="0 0 0" />
179
+ <mass value="0.001" />
180
+ <inertia ixx="0.0001" ixy="0" ixz="0" iyy="0.0001" iyz="0" izz="0.0001" />
181
+ </inertial>
182
+ <visual>
183
+ <origin xyz="0 0 0" rpy="0 0 0" />
184
+ <geometry>
185
+ <mesh filename="package://xpkg_urdf_archer_l6y/meshes/link_6.STL" />
186
+ </geometry>
187
+ <material name="">
188
+ <color rgba="1 1 1 1" />
189
+ </material>
190
+ </visual>
191
+ <collision>
192
+ <origin xyz="0 0 0" rpy="0 0 0" />
193
+ <geometry>
194
+ <mesh filename="package://xpkg_urdf_archer_l6y/meshes/link_6.STL" />
195
+ </geometry>
196
+ </collision>
197
+ </link>
198
+ <joint name="joint_6" type="revolute">
199
+ <origin xyz="0.046 0 0.034" rpy="0 0 0" />
200
+ <parent link="link_5" />
201
+ <child link="link_6" />
202
+ <axis xyz="0 0 1" />
203
+ <limit lower="-3.1415" upper="3.1415" effort="0" velocity="0" />
204
+ </joint>
205
+
206
+ </robot>