hex-zmq-servers 0.3.16__py3-none-any.whl → 1.0.1__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.
@@ -15,7 +15,6 @@ from .zmq_base import HexZMQDummyClient, HexZMQDummyServer
15
15
 
16
16
  from .robot import HexRobotBase, HexRobotClientBase, HexRobotServerBase
17
17
  from .robot import HexRobotDummy, HexRobotDummyClient, HexRobotDummyServer
18
- from .robot import HexRobotGello, HexRobotGelloClient, HexRobotGelloServer
19
18
  from .robot import HexRobotHexarm, HexRobotHexarmClient, HexRobotHexarmServer, HEXARM_URDF_PATH_DICT
20
19
 
21
20
  from .cam import HexCamBase, HexCamClientBase, HexCamServerBase
@@ -28,7 +27,6 @@ file_dir = os.path.dirname(os.path.abspath(__file__))
28
27
  HEX_ZMQ_SERVERS_PATH_DICT = {
29
28
  "zmq_dummy": f"{file_dir}/zmq_base.py",
30
29
  "robot_dummy": f"{file_dir}/robot/dummy/robot_dummy_srv.py",
31
- "robot_gello": f"{file_dir}/robot/gello/robot_gello_srv.py",
32
30
  "robot_hexarm": f"{file_dir}/robot/hexarm/robot_hexarm_srv.py",
33
31
  "cam_dummy": f"{file_dir}/cam/dummy/cam_dummy_srv.py",
34
32
  "cam_rgb": f"{file_dir}/cam/rgb/cam_rgb_srv.py",
@@ -36,7 +34,6 @@ HEX_ZMQ_SERVERS_PATH_DICT = {
36
34
  HEX_ZMQ_CONFIGS_PATH_DICT = {
37
35
  "zmq_dummy": f"{file_dir}/config/zmq_dummy.json",
38
36
  "robot_dummy": f"{file_dir}/config/robot_dummy.json",
39
- "robot_gello": f"{file_dir}/config/robot_gello.json",
40
37
  "robot_hexarm": f"{file_dir}/config/robot_hexarm.json",
41
38
  "cam_dummy": f"{file_dir}/config/cam_dummy.json",
42
39
  "cam_rgb": f"{file_dir}/config/cam_rgb.json",
@@ -80,9 +77,6 @@ __all__ = [
80
77
  "HexRobotDummy",
81
78
  "HexRobotDummyClient",
82
79
  "HexRobotDummyServer",
83
- "HexRobotGello",
84
- "HexRobotGelloClient",
85
- "HexRobotGelloServer",
86
80
  "HexRobotHexarm",
87
81
  "HexRobotHexarmClient",
88
82
  "HexRobotHexarmServer",
@@ -104,6 +98,7 @@ from importlib.util import find_spec
104
98
 
105
99
  _HAS_BERXEL = find_spec("berxel_py_wrapper") is not None
106
100
  _HAS_REALSENSE = find_spec("pyrealsense2") is not None
101
+ _HAS_DYNAMIXEL = find_spec("dynamixel-sdk") is not None
107
102
  _HAS_MUJOCO = find_spec("mujoco") is not None
108
103
 
109
104
  # Optional: berxel
@@ -140,6 +135,23 @@ if _HAS_REALSENSE:
140
135
  "HexCamRealsenseServer",
141
136
  ])
142
137
 
138
+ # Optional: dynamixel
139
+ if _HAS_DYNAMIXEL:
140
+ from .robot import HexRobotGello, HexRobotGelloClient, HexRobotGelloServer
141
+ HEX_ZMQ_SERVERS_PATH_DICT.update({
142
+ "robot_gello":
143
+ f"{file_dir}/robot/gello/robot_gello_srv.py",
144
+ })
145
+ HEX_ZMQ_CONFIGS_PATH_DICT.update({
146
+ "robot_gello":
147
+ f"{file_dir}/config/robot_gello.json",
148
+ })
149
+ __all__.extend([
150
+ "HexRobotGello",
151
+ "HexRobotGelloClient",
152
+ "HexRobotGelloServer",
153
+ ])
154
+
143
155
  # Optional: mujoco
144
156
  if _HAS_MUJOCO:
145
157
  from .mujoco import HexMujocoBase, HexMujocoClientBase, HexMujocoServerBase
@@ -47,8 +47,8 @@ class HexCamBerxel(HexCamBase):
47
47
 
48
48
  # variables
49
49
  # berxel variables
50
- self.__context = None
51
- self.__device = None
50
+ self.__context: BerxelHawkContext | None = None
51
+ self.__device: BerxelHawkDevice | None = None
52
52
  # camera variables
53
53
  self.__intri = np.zeros(4)
54
54
 
@@ -214,7 +214,15 @@ class HexCamBerxel(HexCamBase):
214
214
  return True
215
215
 
216
216
  def __start_stream(self):
217
- self.__device.setColorExposureGain(self.__exposure, self.__gain)
217
+ if self.__serial_number.startswith('P008'):
218
+ self.__device.setSonixAEStatus(False)
219
+ self.__device.setSonixExposureTime(int(self.__exposure // 100))
220
+ else:
221
+ self.__device.setColorExposureGain(self.__exposure, self.__gain)
222
+ self.__device.setDepthElectricCurrent(700)
223
+ self.__device.setDepthAE(False)
224
+ self.__device.setDepthExposure(43)
225
+ self.__device.setDepthGain(1)
218
226
  self.__device.setRegistrationEnable(True)
219
227
  self.__device.setFrameSync(True)
220
228
  while self.__device.setSystemClock() != 0:
@@ -13,7 +13,6 @@
13
13
  "device_port": 8439,
14
14
  "control_hz": 1000,
15
15
  "arm_type": "archer_l6y",
16
- "use_gripper": true,
17
16
  "mit_kp": [
18
17
  200.0,
19
18
  200.0,
@@ -21,7 +20,13 @@
21
20
  75.0,
22
21
  15.0,
23
22
  15.0,
24
- 20.0
23
+ 20.0,
24
+ 0.0,
25
+ 0.0,
26
+ 0.0,
27
+ 0.0,
28
+ 0.0,
29
+ 0.0
25
30
  ],
26
31
  "mit_kd": [
27
32
  12.5,
@@ -30,7 +35,13 @@
30
35
  6.0,
31
36
  0.31,
32
37
  0.31,
33
- 1.0
38
+ 1.0,
39
+ 0.0,
40
+ 0.0,
41
+ 0.0,
42
+ 0.0,
43
+ 0.0,
44
+ 0.0
34
45
  ],
35
46
  "sens_ts": true
36
47
  }
@@ -76,21 +76,36 @@ class HexMujocoArcherY6(HexMujocoBase):
76
76
  mujoco.mj_resetData(self.__model, self.__data)
77
77
 
78
78
  # state init
79
- self.__state_robot_idx = [0, 1, 2, 3, 4, 5, 6]
80
- self.__state_obj_idx = [12, 13, 14, 15, 16, 17, 18]
81
- self.__ctrl_robot_idx = [0, 1, 2, 3, 4, 5, 6]
82
- self.__ctrl_obj_idx = [0, 1, 2, 3, 4, 5, 6]
83
- self._limits = np.stack(
84
- [self.__model.jnt_range[self.__state_robot_idx, :]],
85
- axis=0,
86
- )
79
+ self.__state_idx = {
80
+ "robot_arm": ([0, 1, 2, 3, 4, 5]),
81
+ "robot_gripper": [6],
82
+ "obj": [12, 13, 14, 15, 16, 17, 18],
83
+ }
84
+ self.__ctrl_idx = {
85
+ "robot_arm": [0, 1, 2, 3, 4, 5],
86
+ "robot_gripper": [6],
87
+ }
88
+ self.__limit_idx = {
89
+ "robot_arm":
90
+ np.arange(len(self.__state_idx["robot_arm"])).tolist(),
91
+ "robot_gripper":
92
+ (np.arange(len(self.__state_idx["robot_gripper"])) +
93
+ len(self.__state_idx["robot_arm"])).tolist(),
94
+ }
95
+ print(f"self.__limit_idx: {self.__limit_idx}")
96
+ self._limits = self.__model.jnt_range[np.concatenate(
97
+ [self.__state_idx["robot_arm"], self.
98
+ __state_idx["robot_gripper"]]), :].copy().reshape(-1, 1, 2)
87
99
  if not self.__tau_ctrl:
88
100
  self.__mit_kp = np.ascontiguousarray(np.asarray(self.__mit_kp))
89
101
  self.__mit_kd = np.ascontiguousarray(np.asarray(self.__mit_kd))
90
102
  self.__mit_ctrl = CtrlUtil()
91
103
  self.__gripper_ratio = 1.33 / 1.52
92
104
  self._limits[0, -1] *= self.__gripper_ratio
93
- self._dofs = np.array([len(self.__state_robot_idx)])
105
+ self._dofs = np.array([
106
+ len(self.__state_idx["robot_arm"]),
107
+ len(self.__state_idx["robot_gripper"])
108
+ ])
94
109
  keyframe_id = mujoco.mj_name2id(
95
110
  self.__model,
96
111
  mujoco.mjtObj.mjOBJ_KEY,
@@ -242,16 +257,25 @@ class HexMujocoArcherY6(HexMujocoBase):
242
257
  pos = copy.deepcopy(self.__data.qpos)
243
258
  vel = copy.deepcopy(self.__data.qvel)
244
259
  eff = copy.deepcopy(self.__data.qfrc_actuator)
245
- pos[self.__state_robot_idx[-1]] = pos[
246
- self.__state_robot_idx[-1]] * self.__gripper_ratio
260
+ pos[self.__state_idx["robot_gripper"]] = pos[
261
+ self.__state_idx["robot_gripper"]] * self.__gripper_ratio
247
262
  return self.__mujoco_ts() if self.__sens_ts else hex_zmq_ts_now(
248
263
  ), np.array([
249
- pos[self.__state_robot_idx],
250
- vel[self.__state_robot_idx],
251
- eff[self.__state_robot_idx],
252
- ]).T, self.__data.qpos[self.__state_obj_idx].copy()
264
+ pos[self.__state_idx["robot_arm"] +
265
+ self.__state_idx["robot_gripper"]],
266
+ vel[self.__state_idx["robot_arm"] +
267
+ self.__state_idx["robot_gripper"]],
268
+ eff[self.__state_idx["robot_arm"] +
269
+ self.__state_idx["robot_gripper"]],
270
+ ]).T, self.__data.qpos[self.__state_idx["obj"]].copy()
253
271
 
254
272
  def __set_cmds(self, cmds: np.ndarray):
273
+ state_idx = self.__state_idx["robot_arm"] + self.__state_idx[
274
+ "robot_gripper"]
275
+ ctrl_idx = self.__ctrl_idx["robot_arm"] + self.__ctrl_idx[
276
+ "robot_gripper"]
277
+ limit_idx = self.__limit_idx["robot_arm"] + self.__limit_idx[
278
+ "robot_gripper"]
255
279
  tau_cmds = None
256
280
  if not self.__tau_ctrl:
257
281
  cmd_pos = None
@@ -278,8 +302,8 @@ class HexMujocoArcherY6(HexMujocoBase):
278
302
  raise ValueError(f"The shape of cmds is invalid: {cmds.shape}")
279
303
  tar_pos = self._apply_pos_limits(
280
304
  cmd_pos,
281
- self._limits[0, :, 0],
282
- self._limits[0, :, 1],
305
+ self._limits[limit_idx, 0, 0],
306
+ self._limits[limit_idx, 0, 1],
283
307
  )
284
308
  tar_pos[-1] /= self.__gripper_ratio
285
309
  tau_cmds = self.__mit_ctrl(
@@ -287,13 +311,13 @@ class HexMujocoArcherY6(HexMujocoBase):
287
311
  cmd_kd,
288
312
  tar_pos,
289
313
  tar_vel,
290
- self.__data.qpos[self.__state_robot_idx],
291
- self.__data.qvel[self.__state_robot_idx],
314
+ self.__data.qpos[state_idx],
315
+ self.__data.qvel[state_idx],
292
316
  cmd_tor,
293
317
  )
294
318
  else:
295
319
  tau_cmds = cmds.copy()
296
- self.__data.ctrl[self.__ctrl_robot_idx] = tau_cmds
320
+ self.__data.ctrl[ctrl_idx] = tau_cmds
297
321
 
298
322
  def __get_rgb(self):
299
323
  self.__rgb_cam.update_scene(self.__data, "end_camera")
@@ -77,18 +77,37 @@ class HexMujocoE3Desktop(HexMujocoBase):
77
77
  mujoco.mj_resetData(self.__model, self.__data)
78
78
 
79
79
  # state init
80
- self.__state_left_idx = [0, 1, 2, 3, 4, 5, 6]
81
- self.__state_right_idx = [12, 13, 14, 15, 16, 17, 18]
82
- self.__obj_pose_idx = [24, 25, 26, 27, 28, 29, 30]
83
- self.__ctrl_left_idx = [0, 1, 2, 3, 4, 5, 6]
84
- self.__ctrl_right_idx = [7, 8, 9, 10, 11, 12, 13]
85
- self._limits = np.stack(
86
- [
87
- self.__model.jnt_range[self.__state_left_idx, :],
88
- self.__model.jnt_range[self.__state_right_idx, :]
89
- ],
90
- axis=0,
91
- )
80
+ self.__state_idx = {
81
+ "left_arm": [0, 1, 2, 3, 4, 5],
82
+ "left_gripper": [6],
83
+ "right_arm": [12, 13, 14, 15, 16, 17],
84
+ "right_gripper": [18],
85
+ "obj": [24, 25, 26, 27, 28, 29, 30],
86
+ }
87
+ self.__ctrl_idx = {
88
+ "left_arm": [0, 1, 2, 3, 4, 5],
89
+ "left_gripper": [6],
90
+ "right_arm": [7, 8, 9, 10, 11, 12],
91
+ "right_gripper": [13],
92
+ }
93
+ self.__limit_idx = {
94
+ "left_arm":
95
+ np.arange(len(self.__state_idx["left_arm"])).tolist(),
96
+ "left_gripper": (np.arange(len(self.__state_idx["left_gripper"])) +
97
+ len(self.__state_idx["left_arm"])).tolist(),
98
+ "right_arm": (np.arange(len(self.__state_idx["right_arm"])) +
99
+ len(self.__state_idx["left_arm"]) +
100
+ len(self.__state_idx["left_gripper"])).tolist(),
101
+ "right_gripper":
102
+ (np.arange(len(self.__state_idx["right_gripper"])) +
103
+ len(self.__state_idx["left_arm"]) +
104
+ len(self.__state_idx["left_gripper"]) +
105
+ len(self.__state_idx["right_arm"])).tolist(),
106
+ }
107
+ self._limits = self.__model.jnt_range[np.concatenate([
108
+ self.__state_idx["left_arm"], self.__state_idx["left_gripper"],
109
+ self.__state_idx["right_arm"], self.__state_idx["right_gripper"]
110
+ ]), :].copy().reshape(-1, 1, 2)
92
111
  if not self.__tau_ctrl:
93
112
  self.__mit_kp = np.ascontiguousarray(np.asarray(self.__mit_kp))
94
113
  self.__mit_kd = np.ascontiguousarray(np.asarray(self.__mit_kd))
@@ -97,8 +116,10 @@ class HexMujocoE3Desktop(HexMujocoBase):
97
116
  self._limits[0, -1] *= self.__gripper_ratio
98
117
  self._limits[1, -1] *= self.__gripper_ratio
99
118
  self._dofs = np.array([
100
- len(self.__state_left_idx),
101
- len(self.__state_right_idx),
119
+ len(self.__state_idx["left_arm"]),
120
+ len(self.__state_idx["left_gripper"]),
121
+ len(self.__state_idx["right_arm"]),
122
+ len(self.__state_idx["right_gripper"]),
102
123
  ])
103
124
  keyframe_id = mujoco.mj_name2id(
104
125
  self.__model,
@@ -347,35 +368,47 @@ class HexMujocoE3Desktop(HexMujocoBase):
347
368
  pos = copy.deepcopy(self.__data.qpos)
348
369
  vel = copy.deepcopy(self.__data.qvel)
349
370
  eff = copy.deepcopy(self.__data.qfrc_actuator)
350
- pos[self.__state_left_idx[-1]] = pos[
351
- self.__state_left_idx[-1]] * self.__gripper_ratio
352
- pos[self.__state_right_idx[-1]] = pos[
353
- self.__state_right_idx[-1]] * self.__gripper_ratio
371
+ pos[self.__state_idx["left_gripper"]] = pos[
372
+ self.__state_idx["left_gripper"]] * self.__gripper_ratio
373
+ pos[self.__state_idx["right_gripper"]] = pos[
374
+ self.__state_idx["right_gripper"]] * self.__gripper_ratio
354
375
  return self.__mujoco_ts() if self.__sens_ts else hex_zmq_ts_now(
355
376
  ), np.array([
356
- pos[self.__state_left_idx],
357
- vel[self.__state_left_idx],
358
- eff[self.__state_left_idx],
377
+ pos[self.__state_idx["left_arm"] +
378
+ self.__state_idx["left_gripper"]],
379
+ vel[self.__state_idx["left_arm"] +
380
+ self.__state_idx["left_gripper"]],
381
+ eff[self.__state_idx["left_arm"] +
382
+ self.__state_idx["left_gripper"]],
359
383
  ]).T, np.array([
360
- pos[self.__state_right_idx],
361
- vel[self.__state_right_idx],
362
- eff[self.__state_right_idx],
363
- ]).T, self.__data.qpos[self.__obj_pose_idx].copy()
384
+ pos[self.__state_idx["right_arm"] +
385
+ self.__state_idx["right_gripper"]],
386
+ vel[self.__state_idx["right_arm"] +
387
+ self.__state_idx["right_gripper"]],
388
+ eff[self.__state_idx["right_arm"] +
389
+ self.__state_idx["right_gripper"]],
390
+ ]).T, self.__data.qpos[self.__state_idx["obj"]].copy()
364
391
 
365
392
  def __set_cmds(self, cmds: np.ndarray, robot_name: str):
366
- ctrl_idx = []
367
- state_idx = []
393
+ state_idx = None
394
+ ctrl_idx = None
368
395
  limit_idx = None
369
396
  if robot_name == "left":
370
- ctrl_idx = self.__ctrl_left_idx
397
+ ctrl_idx = self.__ctrl_idx["left_arm"] + self.__ctrl_idx[
398
+ "left_gripper"]
371
399
  if not self.__tau_ctrl:
372
- state_idx = self.__state_left_idx
373
- limit_idx = 0
400
+ state_idx = self.__state_idx["left_arm"] + self.__state_idx[
401
+ "left_gripper"]
402
+ limit_idx = self.__limit_idx["left_arm"] + self.__limit_idx[
403
+ "left_gripper"]
374
404
  elif robot_name == "right":
375
- ctrl_idx = self.__ctrl_right_idx
405
+ ctrl_idx = self.__ctrl_idx["right_arm"] + self.__ctrl_idx[
406
+ "right_gripper"]
376
407
  if not self.__tau_ctrl:
377
- state_idx = self.__state_right_idx
378
- limit_idx = 1
408
+ state_idx = self.__state_idx["right_arm"] + self.__state_idx[
409
+ "right_gripper"]
410
+ limit_idx = self.__limit_idx["right_arm"] + self.__limit_idx[
411
+ "right_gripper"]
379
412
  else:
380
413
  raise ValueError(f"unknown robot name: {robot_name}")
381
414
  tau_cmds = None
@@ -404,8 +437,8 @@ class HexMujocoE3Desktop(HexMujocoBase):
404
437
  raise ValueError(f"The shape of cmds is invalid: {cmds.shape}")
405
438
  tar_pos = self._apply_pos_limits(
406
439
  cmd_pos,
407
- self._limits[limit_idx, :, 0],
408
- self._limits[limit_idx, :, 1],
440
+ self._limits[limit_idx, 0, 0],
441
+ self._limits[limit_idx, 0, 1],
409
442
  )
410
443
  tar_pos[-1] /= self.__gripper_ratio
411
444
  tau_cmds = self.__mit_ctrl(
@@ -8,7 +8,6 @@
8
8
 
9
9
  from .robot_base import HexRobotBase, HexRobotClientBase, HexRobotServerBase
10
10
  from .dummy import HexRobotDummy, HexRobotDummyClient, HexRobotDummyServer
11
- from .gello import HexRobotGello, HexRobotGelloClient, HexRobotGelloServer
12
11
  from .hexarm import HexRobotHexarm, HexRobotHexarmClient, HexRobotHexarmServer, HEXARM_URDF_PATH_DICT
13
12
 
14
13
  __all__ = [
@@ -25,13 +24,22 @@ __all__ = [
25
24
  "HexRobotDummyClient",
26
25
  "HexRobotDummyServer",
27
26
 
28
- # gello
29
- "HexRobotGello",
30
- "HexRobotGelloClient",
31
- "HexRobotGelloServer",
32
-
33
27
  # hexarm
34
28
  "HexRobotHexarm",
35
29
  "HexRobotHexarmClient",
36
30
  "HexRobotHexarmServer",
37
31
  ]
32
+
33
+ # Check optional dependencies availability
34
+ from importlib.util import find_spec
35
+
36
+ _HAS_DYNAMIXEL = find_spec("dynamixel-sdk") is not None
37
+
38
+ # Optional: dynamixel
39
+ if _HAS_DYNAMIXEL:
40
+ from .gello import HexRobotGello, HexRobotGelloClient, HexRobotGelloServer
41
+ __all__.extend([
42
+ "HexRobotGello",
43
+ "HexRobotGelloClient",
44
+ "HexRobotGelloServer",
45
+ ])
@@ -46,6 +46,8 @@ HEXARM_URDF_PATH_DICT = {
46
46
  f"{urdf_dir}/archer_l6y/gp100_p050_handle.urdf",
47
47
  "firefly_y6_empty":
48
48
  f"{urdf_dir}/firefly_y6/empty.urdf",
49
+ "archer_d6y_gp80":
50
+ f"{urdf_dir}/archer_d6y/gp80.urdf",
49
51
  }
50
52
 
51
53
  __all__ = [
@@ -18,7 +18,7 @@ from ...zmq_base import (
18
18
  HexRate,
19
19
  )
20
20
  from ...hex_launch import hex_log, HEX_LOG_LEVEL
21
- from hex_device import HexDeviceApi, MotorBase
21
+ from hex_device import HexDeviceApi, Arm, Hands
22
22
  from hex_device.motor_base import CommandType
23
23
 
24
24
  ROBOT_CONFIG = {
@@ -26,7 +26,6 @@ ROBOT_CONFIG = {
26
26
  "device_port": 8439,
27
27
  "control_hz": 250,
28
28
  "arm_type": "archer_y6",
29
- "use_gripper": True,
30
29
  "mit_kp": [200.0, 200.0, 200.0, 75.0, 15.0, 15.0, 20.0],
31
30
  "mit_kd": [12.5, 12.5, 12.5, 6.0, 0.31, 0.31, 1.0],
32
31
  "sens_ts": True,
@@ -37,6 +36,7 @@ HEX_DEVICE_TYPE_DICT = {
37
36
  "archer_d6y": 16,
38
37
  "archer_l6y": 17,
39
38
  "firefly_y6": 27,
39
+ "hello": 26,
40
40
  }
41
41
 
42
42
 
@@ -54,7 +54,6 @@ class HexRobotHexarm(HexRobotBase):
54
54
  device_port = robot_config["device_port"]
55
55
  control_hz = robot_config["control_hz"]
56
56
  arm_type = HEX_DEVICE_TYPE_DICT[robot_config["arm_type"]]
57
- use_gripper = robot_config["use_gripper"]
58
57
  self.__sens_ts = robot_config["sens_ts"]
59
58
  except KeyError as ke:
60
59
  missing_key = ke.args[0]
@@ -73,8 +72,8 @@ class HexRobotHexarm(HexRobotBase):
73
72
  # variables
74
73
  # hex_arm variables
75
74
  self.__hex_api: HexDeviceApi | None = None
76
- self.__arm_archer: MotorBase | None = None
77
- self.__gripper: MotorBase | None = None
75
+ self.__arm: Arm | None = None
76
+ self.__gripper: Hands | None = None
78
77
 
79
78
  # buffer
80
79
  self.__arm_state_buffer: dict | None = None
@@ -90,40 +89,46 @@ class HexRobotHexarm(HexRobotBase):
90
89
  while self.__hex_api.find_device_by_robot_type(arm_type) is None:
91
90
  print("\033[33mArm not found\033[0m")
92
91
  time.sleep(1)
93
- self.__arm_archer = self.__hex_api.find_device_by_robot_type(arm_type)
94
- self.__arm_archer.start()
95
- self.__arm_dofs = len(self.__arm_archer)
96
- self._limits = self.__arm_archer.get_joint_limits()
92
+ self.__arm = self.__hex_api.find_device_by_robot_type(arm_type)
93
+ self.__arm.start()
97
94
 
98
95
  # try to open gripper
99
- self.__gripper_dofs = 0
100
- self.__gripper = None
101
- if use_gripper:
102
- self.__gripper = self.__hex_api.find_optional_device_by_id(1)
103
- if self.__gripper is not None:
104
- self.__gripper_dofs = len(self.__gripper)
105
- self._limits += [self.__gripper.get_joint_limits()]
106
- else:
107
- print("\033[33mGripper not found\033[0m")
96
+ self.__gripper = self.__hex_api.find_optional_device_by_id(1)
97
+ if self.__gripper is None:
98
+ print("\033[33mGripper not found\033[0m")
99
+
100
+ # variables init
101
+ arm_dofs = len(self.__arm)
102
+ self._dofs = [arm_dofs]
103
+ self._limits = np.array(self.__arm.get_joint_limits()).reshape(-1, 3, 2)
104
+ self.__motor_idx = {"robot_arm": np.arange(arm_dofs).tolist()}
105
+ if self.__gripper is not None:
106
+ gripper_dofs = len(self.__gripper)
107
+ self._dofs.append(gripper_dofs)
108
+ gripper_limits = np.array(self.__gripper.get_joint_limits()).reshape(-1, 3, 2)
109
+ self._limits = np.concatenate([self._limits, gripper_limits], axis=0)
110
+ self.__motor_idx["robot_gripper"] = (np.arange(gripper_dofs) +
111
+ arm_dofs).tolist()
108
112
 
109
113
  # modify variables
110
- self._dofs = [self.__arm_dofs + self.__gripper_dofs]
114
+ self._dofs = np.array(self._dofs)
115
+ self._dofs_sum = self._dofs.sum()
111
116
  self._limits = np.ascontiguousarray(np.asarray(self._limits)).reshape(
112
- self._dofs[0], 3, 2)
117
+ self._dofs_sum, 3, 2)
113
118
  self.__mit_kp = np.ascontiguousarray(np.asarray(self.__mit_kp))
114
119
  self.__mit_kd = np.ascontiguousarray(np.asarray(self.__mit_kd))
115
- if self.__mit_kp.shape[0] < self._dofs[0] or self.__mit_kd.shape[
116
- 0] < self._dofs[0]:
120
+ if self.__mit_kp.shape[0] < self._dofs_sum or self.__mit_kd.shape[
121
+ 0] < self._dofs_sum:
117
122
  raise ValueError(
118
123
  "The length of mit_kp and mit_kd must be greater than or equal to the number of motors"
119
124
  )
120
- elif self.__mit_kp.shape[0] > self._dofs[0] or self.__mit_kd.shape[
121
- 0] > self._dofs[0]:
125
+ elif self.__mit_kp.shape[0] > self._dofs_sum or self.__mit_kd.shape[
126
+ 0] > self._dofs_sum:
122
127
  print(
123
128
  f"\033[33mThe length of mit_kp and mit_kd is greater than the number of motors\033[0m"
124
129
  )
125
- self.__mit_kp = self.__mit_kp[:self._dofs[0]]
126
- self.__mit_kd = self.__mit_kd[:self._dofs[0]]
130
+ self.__mit_kp = self.__mit_kp[:self._dofs_sum]
131
+ self.__mit_kd = self.__mit_kd[:self._dofs_sum]
127
132
 
128
133
  # start work loop
129
134
  self._working.set()
@@ -167,13 +172,12 @@ class HexRobotHexarm(HexRobotBase):
167
172
  self.close()
168
173
 
169
174
  def __get_states(self) -> tuple[np.ndarray | None, dict | None]:
170
- if self.__arm_archer is None:
175
+ if self.__arm is None:
171
176
  return None, None
172
177
 
173
178
  # (arm_dofs, 3) # pos vel eff
174
179
  if self.__arm_state_buffer is None:
175
- self.__arm_state_buffer = self.__arm_archer.get_simple_motor_status(
176
- )
180
+ self.__arm_state_buffer = self.__arm.get_simple_motor_status()
177
181
 
178
182
  # (gripper_dofs, 3) # pos vel eff
179
183
  if self.__gripper is not None and self.__gripper_state_buffer is None:
@@ -220,24 +224,24 @@ class HexRobotHexarm(HexRobotBase):
220
224
  # [[pos_0, tor_0], ..., [pos_n, tor_n]]
221
225
  # cmds: (n, 5)
222
226
  # [[pos_0, vel_0, tor_0, kp_0, kd_0], ..., [pos_n, vel_n, tor_n, kp_n, kd_n]]
223
- if self.__arm_archer is None:
227
+ if self.__arm is None:
224
228
  print("\033[91mArm not found\033[0m")
225
229
  return False
226
230
 
227
- if cmds.shape[0] < self._dofs[0]:
231
+ if cmds.shape[0] < self._dofs_sum:
228
232
  print(
229
233
  "\033[91mThe length of joint_angles must be greater than or equal to the number of motors\033[0m"
230
234
  )
231
235
  return False
232
- elif cmds.shape[0] > self._dofs[0]:
236
+ elif cmds.shape[0] > self._dofs_sum:
233
237
  print(
234
238
  f"\033[33mThe length of joint_angles is greater than the number of motors\033[0m"
235
239
  )
236
- cmds = cmds[:self._dofs[0]]
240
+ cmds = cmds[:self._dofs_sum]
237
241
 
238
242
  cmd_pos = None
239
- tar_vel = np.zeros(self._dofs[0])
240
- cmd_tor = np.zeros(self._dofs[0])
243
+ tar_vel = np.zeros(self._dofs_sum)
244
+ cmd_tor = np.zeros(self._dofs_sum)
241
245
  cmd_kp = self.__mit_kp.copy()
242
246
  cmd_kd = self.__mit_kd.copy()
243
247
  if len(cmds.shape) == 1:
@@ -263,25 +267,25 @@ class HexRobotHexarm(HexRobotBase):
263
267
  )
264
268
 
265
269
  # arm
266
- mit_cmd = self.__arm_archer.construct_mit_command(
267
- tar_pos[:self.__arm_dofs],
268
- tar_vel[:self.__arm_dofs],
269
- cmd_tor[:self.__arm_dofs],
270
- cmd_kp[:self.__arm_dofs],
271
- cmd_kd[:self.__arm_dofs],
270
+ arm_cmd = self.__arm.construct_mit_command(
271
+ tar_pos[self.__motor_idx["robot_arm"]],
272
+ tar_vel[self.__motor_idx["robot_arm"]],
273
+ cmd_tor[self.__motor_idx["robot_arm"]],
274
+ cmd_kp[self.__motor_idx["robot_arm"]],
275
+ cmd_kd[self.__motor_idx["robot_arm"]],
272
276
  )
273
- self.__arm_archer.motor_command(CommandType.MIT, mit_cmd)
277
+ self.__arm.motor_command(CommandType.MIT, arm_cmd)
274
278
 
275
279
  # gripper
276
280
  if self.__gripper is not None:
277
- mit_cmd = self.__gripper.construct_mit_command(
278
- tar_pos[self.__arm_dofs:],
279
- tar_vel[self.__arm_dofs:],
280
- cmd_tor[self.__arm_dofs:],
281
- cmd_kp[self.__arm_dofs:],
282
- cmd_kd[self.__arm_dofs:],
281
+ gripper_cmd = self.__gripper.construct_mit_command(
282
+ tar_pos[self.__motor_idx["robot_gripper"]],
283
+ tar_vel[self.__motor_idx["robot_gripper"]],
284
+ cmd_tor[self.__motor_idx["robot_gripper"]],
285
+ cmd_kp[self.__motor_idx["robot_gripper"]],
286
+ cmd_kd[self.__motor_idx["robot_gripper"]],
283
287
  )
284
- self.__gripper.motor_command(CommandType.MIT, mit_cmd)
288
+ self.__gripper.motor_command(CommandType.MIT, gripper_cmd)
285
289
 
286
290
  return True
287
291
 
@@ -289,6 +293,6 @@ class HexRobotHexarm(HexRobotBase):
289
293
  if not self._working.is_set():
290
294
  return
291
295
  self._working.clear()
292
- self.__arm_archer.stop()
296
+ self.__arm.stop()
293
297
  self.__hex_api.close()
294
298
  hex_log(HEX_LOG_LEVEL["info"], "HexRobotHexarm closed")
@@ -36,9 +36,8 @@ ROBOT_CONFIG = {
36
36
  "device_port": 8439,
37
37
  "control_hz": 250,
38
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],
39
+ "mit_kp": [200.0, 200.0, 200.0, 75.0, 15.0, 15.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
40
+ "mit_kd": [12.5, 12.5, 12.5, 6.0, 0.31, 0.31, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
42
41
  "sens_ts": True,
43
42
  }
44
43