diff --git a/README.md b/README.md
index f14ac0f..8a1908b 100644
--- a/README.md
+++ b/README.md
@@ -156,38 +156,15 @@ Copy the `rootCA.pem` via AirDrop to Apple Vision Pro and install it.
Settings > General > About > Certificate Trust Settings. Under "Enable full trust for root certificates", turn on trust for the certificate.
+> In the new version of Vision OS 2, this step is different: After copying the certificate to the Apple Vision Pro device via AirDrop, a certificate-related information section will appear below the account bar in the top left corner of the Settings app. Tap it to enable trust for the certificate.
+
Settings > Apps > Safari > Advanced > Feature Flags > Enable WebXR Related Features.
-## 2.3 🔎 Test environment
+## 2.3 🔎 Unit Test
This step is to verify that the environment is installed correctly.
-1. Download Isaac Gym: https://developer.nvidia.com/isaac-gym/download
-
- Extracting to the current directory, go to the `IsaacGym_Preview_4_Package/isaacgym/python` directory and execute the command:
-
- ```bash
- (tv) unitree@Host:~/IsaacGym_Preview_4_Package/isaacgym/python$ pip install -e .
- ```
-
-2. After setup up streaming with local following the above instructions, you can try teleoperating two robot hands in Issac Gym:
-
- ```bash
- (tv) unitree@Host:~/avp_teleoperate$ cd teleop
- (tv) unitree@Host:~/avp_teleoperate/teleop$ python teleop_test_gym.py
- ```
-
-3. Wear your Apple Vision Pro device.
-
-4. Open Safari on Apple Vision Pro and visit: https://192.168.123.2:8012?ws=wss://192.168.123.2:8012
-
- > p.s. This IP address should match the IP address of your **Host machine**.
-
-5. Click `Enter VR` and `Allow` to start the VR session.
-
-6. See your hands in 3D!
-
-
+comming soon.
diff --git a/README_zh-CN.md b/README_zh-CN.md
index 51f820a..6d0fbfd 100644
--- a/README_zh-CN.md
+++ b/README_zh-CN.md
@@ -159,36 +159,13 @@ unitree@Host:~$ conda activate tv
设置 > 应用 > Safari > 高级 > 功能标志 > 启用 WebXR 相关功能。
-## 2.3 🔎 测试环境
+> 提醒:在新版本 Vision OS 2 系统中,该步骤有所不同:将证书通过 AirDrop 复制到 Apple Vision Pro 设备后,将会在设置 APP 中左上角账户栏的下方出现证书相关信息栏,点击进去即可启用对该证书的信任。
-此步骤用于验证环境是否正确安装。
-
-1. 下载 Isaac Gym:https://developer.nvidia.com/isaac-gym/download
-
- 解压到当前目录,进入 `IsaacGym_Preview_4_Package/isaacgym/python` 目录,执行命令:
-
- ```bash
- (tv) unitree@Host:~/IsaacGym_Preview_4_Package/isaacgym/python$ pip install -e .
- ```
-
-2. 按照上述说明设置本地流媒体后,您可以尝试在 Isaac Gym 中远程操作两个机器人手:
-
- ```bash
- (tv) unitree@Host:~/avp_teleoperate$ cd teleop
- (tv) unitree@Host:~/avp_teleoperate/teleop$ python teleop_test_gym.py
- ```
-
-3. 戴上您的 Apple Vision Pro 设备。
-
-4. 在 Apple Vision Pro 上打开 Safari,访问:https://192.168.123.2:8012?ws=wss://192.168.123.2:8012
-
- > 提醒:此 IP 地址应与您的 **主机** IP 地址匹配。
-
-5. 点击 `Enter VR` 并选择 `Allow` 以启动 VR 会话。
-
-6. 在 3D 中看到您的手!
+## 2.3 🔎 单元测试
+此步骤用于验证环境是否正确安装。
+即将展现。
diff --git a/assets/h1_2/README.md b/assets/h1_2/README.md
new file mode 100644
index 0000000..6e8f8c5
--- /dev/null
+++ b/assets/h1_2/README.md
@@ -0,0 +1,79 @@
+# Unitree H1 Description (URDF & MJCF)
+
+## Overview
+
+This package includes a streamlined robot description (URDF & MJCF) for the [Unitree H1](https://www.unitree.com/h1/), developed by [Unitree Robotics](https://www.unitree.com/).
+
+
+
+
+
+Unitree H1 have 51 DOFs:
+
+```text
+root [⚓] => /pelvis/
+ left_hip_yaw_joint [⚙+Z] => /left_hip_yaw_link/
+ left_hip_pitch_joint [⚙+Y] => /left_hip_pitch_link/
+ left_hip_roll_joint [⚙+X] => /left_hip_roll_link/
+ left_knee_joint [⚙+Y] => /left_knee_link/
+ left_ankle_pitch_joint [⚙+Y] => /left_ankle_pitch_link/
+ left_ankle_roll_joint [⚙+X] => /left_ankle_roll_link/
+ right_hip_yaw_joint [⚙+Z] => /right_hip_yaw_link/
+ right_hip_pitch_joint [⚙+Y] => /right_hip_pitch_link/
+ right_hip_roll_joint [⚙+X] => /right_hip_roll_link/
+ right_knee_joint [⚙+Y] => /right_knee_link/
+ right_ankle_pitch_joint [⚙+Y] => /right_ankle_pitch_link/
+ right_ankle_roll_joint [⚙+X] => /right_ankle_roll_link/
+ torso_joint [⚙+Z] => /torso_link/
+ left_shoulder_pitch_joint [⚙+Y] => /left_shoulder_pitch_link/
+ left_shoulder_roll_joint [⚙+X] => /left_shoulder_roll_link/
+ left_shoulder_yaw_joint [⚙+Z] => /left_shoulder_yaw_link/
+ left_elbow_pitch_joint [⚙+Y] => /left_elbow_pitch_link/
+ left_elbow_roll_joint [⚙+X] => /left_elbow_roll_link/
+ left_wrist_pitch_joint [⚙+Y] => /left_wrist_pitch_link/
+ left_wrist_yaw_joint [⚙+Z] => /left_wrist_yaw_link/
+ L_base_link_joint [⚓] => /L_hand_base_link/
+ L_thumb_proximal_yaw_joint [⚙+Z] => /L_thumb_proximal_base/
+ L_thumb_proximal_pitch_joint [⚙-Z] => /L_thumb_proximal/
+ L_thumb_intermediate_joint [⚙-Z] => /L_thumb_intermediate/
+ L_thumb_distal_joint [⚙-Z] => /L_thumb_distal/
+ L_index_proximal_joint [⚙-Z] => /L_index_proximal/
+ L_index_intermediate_joint [⚙-Z] => /L_index_intermediate/
+ L_middle_proximal_joint [⚙-Z] => /L_middle_proximal/
+ L_middle_intermediate_joint [⚙-Z] => /L_middle_intermediate/
+ L_ring_proximal_joint [⚙-Z] => /L_ring_proximal/
+ L_ring_intermediate_joint [⚙-Z] => /L_ring_intermediate/
+ L_pinky_proximal_joint [⚙-Z] => /L_pinky_proximal/
+ L_pinky_intermediate_joint [⚙-Z] => /L_pinky_intermediate/
+ right_shoulder_pitch_joint [⚙+Y] => /right_shoulder_pitch_link/
+ right_shoulder_roll_joint [⚙+X] => /right_shoulder_roll_link/
+ right_shoulder_yaw_joint [⚙+Z] => /right_shoulder_yaw_link/
+ right_elbow_pitch_joint [⚙+Y] => /right_elbow_pitch_link/
+ right_elbow_roll_joint [⚙+X] => /right_elbow_roll_link/
+ right_wrist_pitch_joint [⚙+Y] => /right_wrist_pitch_link/
+ right_wrist_yaw_joint [⚙+Z] => /right_wrist_yaw_link/
+ R_base_link_joint [⚓] => /R_hand_base_link/
+ R_thumb_proximal_yaw_joint [⚙-Z] => /R_thumb_proximal_base/
+ R_thumb_proximal_pitch_joint [⚙+Z] => /R_thumb_proximal/
+ R_thumb_intermediate_joint [⚙+Z] => /R_thumb_intermediate/
+ R_thumb_distal_joint [⚙+Z] => /R_thumb_distal/
+ R_index_proximal_joint [⚙+Z] => /R_index_proximal/
+ R_index_intermediate_joint [⚙+Z] => /R_index_intermediate/
+ R_middle_proximal_joint [⚙+Z] => /R_middle_proximal/
+ R_middle_intermediate_joint [⚙+Z] => /R_middle_intermediate/
+ R_ring_proximal_joint [⚙+Z] => /R_ring_proximal/
+ R_ring_intermediate_joint [⚙+Z] => /R_ring_intermediate/
+ R_pinky_proximal_joint [⚙+Z] => /R_pinky_proximal/
+ R_pinky_intermediate_joint [⚙+Z] => /R_pinky_intermediate/
+```
+
+## Visulization with [MuJoCo](https://github.com/google-deepmind/mujoco)
+
+1. Open MuJoCo Viewer
+
+ ```bash
+ pip install mujoco
+ python -m mujoco.viewer
+ ```
+
+2. Drag and drop the MJCF model file (`scene.xml`) to the MuJoCo Viewer.
diff --git a/assets/h1_2/h1_2.urdf b/assets/h1_2/h1_2.urdf
new file mode 100644
index 0000000..c3ea576
--- /dev/null
+++ b/assets/h1_2/h1_2.urdf
@@ -0,0 +1,1623 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/h1_2/h1_2.xml b/assets/h1_2/h1_2.xml
new file mode 100644
index 0000000..00ee6b0
--- /dev/null
+++ b/assets/h1_2/h1_2.xml
@@ -0,0 +1,438 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/h1_2/meshes/L_hand_base_link.STL b/assets/h1_2/meshes/L_hand_base_link.STL
new file mode 100644
index 0000000..a2f67ee
Binary files /dev/null and b/assets/h1_2/meshes/L_hand_base_link.STL differ
diff --git a/assets/h1_2/meshes/L_index_intermediate.STL b/assets/h1_2/meshes/L_index_intermediate.STL
new file mode 100644
index 0000000..24a5a83
Binary files /dev/null and b/assets/h1_2/meshes/L_index_intermediate.STL differ
diff --git a/assets/h1_2/meshes/L_index_proximal.STL b/assets/h1_2/meshes/L_index_proximal.STL
new file mode 100644
index 0000000..f899431
Binary files /dev/null and b/assets/h1_2/meshes/L_index_proximal.STL differ
diff --git a/assets/h1_2/meshes/L_middle_intermediate.STL b/assets/h1_2/meshes/L_middle_intermediate.STL
new file mode 100644
index 0000000..c498cd7
Binary files /dev/null and b/assets/h1_2/meshes/L_middle_intermediate.STL differ
diff --git a/assets/h1_2/meshes/L_middle_proximal.STL b/assets/h1_2/meshes/L_middle_proximal.STL
new file mode 100644
index 0000000..8f0aca6
Binary files /dev/null and b/assets/h1_2/meshes/L_middle_proximal.STL differ
diff --git a/assets/h1_2/meshes/L_pinky_intermediate.STL b/assets/h1_2/meshes/L_pinky_intermediate.STL
new file mode 100644
index 0000000..6b9cdad
Binary files /dev/null and b/assets/h1_2/meshes/L_pinky_intermediate.STL differ
diff --git a/assets/h1_2/meshes/L_pinky_proximal.STL b/assets/h1_2/meshes/L_pinky_proximal.STL
new file mode 100644
index 0000000..ccb63bf
Binary files /dev/null and b/assets/h1_2/meshes/L_pinky_proximal.STL differ
diff --git a/assets/h1_2/meshes/L_ring_intermediate.STL b/assets/h1_2/meshes/L_ring_intermediate.STL
new file mode 100644
index 0000000..23c4efa
Binary files /dev/null and b/assets/h1_2/meshes/L_ring_intermediate.STL differ
diff --git a/assets/h1_2/meshes/L_ring_proximal.STL b/assets/h1_2/meshes/L_ring_proximal.STL
new file mode 100644
index 0000000..c3cabb9
Binary files /dev/null and b/assets/h1_2/meshes/L_ring_proximal.STL differ
diff --git a/assets/h1_2/meshes/L_thumb_distal.STL b/assets/h1_2/meshes/L_thumb_distal.STL
new file mode 100644
index 0000000..291a14f
Binary files /dev/null and b/assets/h1_2/meshes/L_thumb_distal.STL differ
diff --git a/assets/h1_2/meshes/L_thumb_intermediate.STL b/assets/h1_2/meshes/L_thumb_intermediate.STL
new file mode 100644
index 0000000..03a3425
Binary files /dev/null and b/assets/h1_2/meshes/L_thumb_intermediate.STL differ
diff --git a/assets/h1_2/meshes/L_thumb_proximal.STL b/assets/h1_2/meshes/L_thumb_proximal.STL
new file mode 100644
index 0000000..08071d3
Binary files /dev/null and b/assets/h1_2/meshes/L_thumb_proximal.STL differ
diff --git a/assets/h1_2/meshes/L_thumb_proximal_base.STL b/assets/h1_2/meshes/L_thumb_proximal_base.STL
new file mode 100644
index 0000000..9933a6c
Binary files /dev/null and b/assets/h1_2/meshes/L_thumb_proximal_base.STL differ
diff --git a/assets/h1_2/meshes/R_hand_base_link.STL b/assets/h1_2/meshes/R_hand_base_link.STL
new file mode 100644
index 0000000..3478a98
Binary files /dev/null and b/assets/h1_2/meshes/R_hand_base_link.STL differ
diff --git a/assets/h1_2/meshes/R_index_intermediate.STL b/assets/h1_2/meshes/R_index_intermediate.STL
new file mode 100644
index 0000000..0cf0f8d
Binary files /dev/null and b/assets/h1_2/meshes/R_index_intermediate.STL differ
diff --git a/assets/h1_2/meshes/R_index_proximal.STL b/assets/h1_2/meshes/R_index_proximal.STL
new file mode 100644
index 0000000..cbfc711
Binary files /dev/null and b/assets/h1_2/meshes/R_index_proximal.STL differ
diff --git a/assets/h1_2/meshes/R_middle_intermediate.STL b/assets/h1_2/meshes/R_middle_intermediate.STL
new file mode 100644
index 0000000..ebc2616
Binary files /dev/null and b/assets/h1_2/meshes/R_middle_intermediate.STL differ
diff --git a/assets/h1_2/meshes/R_middle_proximal.STL b/assets/h1_2/meshes/R_middle_proximal.STL
new file mode 100644
index 0000000..3f630a3
Binary files /dev/null and b/assets/h1_2/meshes/R_middle_proximal.STL differ
diff --git a/assets/h1_2/meshes/R_pinky_intermediate.STL b/assets/h1_2/meshes/R_pinky_intermediate.STL
new file mode 100644
index 0000000..c2cf58b
Binary files /dev/null and b/assets/h1_2/meshes/R_pinky_intermediate.STL differ
diff --git a/assets/h1_2/meshes/R_pinky_proximal.STL b/assets/h1_2/meshes/R_pinky_proximal.STL
new file mode 100644
index 0000000..d4710f1
Binary files /dev/null and b/assets/h1_2/meshes/R_pinky_proximal.STL differ
diff --git a/assets/h1_2/meshes/R_ring_intermediate.STL b/assets/h1_2/meshes/R_ring_intermediate.STL
new file mode 100644
index 0000000..5fed852
Binary files /dev/null and b/assets/h1_2/meshes/R_ring_intermediate.STL differ
diff --git a/assets/h1_2/meshes/R_ring_proximal.STL b/assets/h1_2/meshes/R_ring_proximal.STL
new file mode 100644
index 0000000..5c3703e
Binary files /dev/null and b/assets/h1_2/meshes/R_ring_proximal.STL differ
diff --git a/assets/h1_2/meshes/R_thumb_distal.STL b/assets/h1_2/meshes/R_thumb_distal.STL
new file mode 100644
index 0000000..13f98f8
Binary files /dev/null and b/assets/h1_2/meshes/R_thumb_distal.STL differ
diff --git a/assets/h1_2/meshes/R_thumb_intermediate.STL b/assets/h1_2/meshes/R_thumb_intermediate.STL
new file mode 100644
index 0000000..a42829f
Binary files /dev/null and b/assets/h1_2/meshes/R_thumb_intermediate.STL differ
diff --git a/assets/h1_2/meshes/R_thumb_proximal.STL b/assets/h1_2/meshes/R_thumb_proximal.STL
new file mode 100644
index 0000000..137dbde
Binary files /dev/null and b/assets/h1_2/meshes/R_thumb_proximal.STL differ
diff --git a/assets/h1_2/meshes/R_thumb_proximal_base.STL b/assets/h1_2/meshes/R_thumb_proximal_base.STL
new file mode 100644
index 0000000..30817a8
Binary files /dev/null and b/assets/h1_2/meshes/R_thumb_proximal_base.STL differ
diff --git a/assets/h1_2/meshes/left_ankle_A_link.STL b/assets/h1_2/meshes/left_ankle_A_link.STL
new file mode 100644
index 0000000..541cb71
Binary files /dev/null and b/assets/h1_2/meshes/left_ankle_A_link.STL differ
diff --git a/assets/h1_2/meshes/left_ankle_A_rod_link.STL b/assets/h1_2/meshes/left_ankle_A_rod_link.STL
new file mode 100644
index 0000000..281dc11
Binary files /dev/null and b/assets/h1_2/meshes/left_ankle_A_rod_link.STL differ
diff --git a/assets/h1_2/meshes/left_ankle_B_link.STL b/assets/h1_2/meshes/left_ankle_B_link.STL
new file mode 100644
index 0000000..cd54990
Binary files /dev/null and b/assets/h1_2/meshes/left_ankle_B_link.STL differ
diff --git a/assets/h1_2/meshes/left_ankle_B_rod_link.STL b/assets/h1_2/meshes/left_ankle_B_rod_link.STL
new file mode 100644
index 0000000..8d80e0a
Binary files /dev/null and b/assets/h1_2/meshes/left_ankle_B_rod_link.STL differ
diff --git a/assets/h1_2/meshes/left_ankle_pitch_link.STL b/assets/h1_2/meshes/left_ankle_pitch_link.STL
new file mode 100644
index 0000000..827fb2c
Binary files /dev/null and b/assets/h1_2/meshes/left_ankle_pitch_link.STL differ
diff --git a/assets/h1_2/meshes/left_ankle_roll_link.STL b/assets/h1_2/meshes/left_ankle_roll_link.STL
new file mode 100644
index 0000000..5fe6027
Binary files /dev/null and b/assets/h1_2/meshes/left_ankle_roll_link.STL differ
diff --git a/assets/h1_2/meshes/left_elbow_pitch_link.STL b/assets/h1_2/meshes/left_elbow_pitch_link.STL
new file mode 100644
index 0000000..55ace3f
Binary files /dev/null and b/assets/h1_2/meshes/left_elbow_pitch_link.STL differ
diff --git a/assets/h1_2/meshes/left_elbow_roll_link.STL b/assets/h1_2/meshes/left_elbow_roll_link.STL
new file mode 100644
index 0000000..112437b
Binary files /dev/null and b/assets/h1_2/meshes/left_elbow_roll_link.STL differ
diff --git a/assets/h1_2/meshes/left_hand_link.STL b/assets/h1_2/meshes/left_hand_link.STL
new file mode 100644
index 0000000..6ce2dcf
Binary files /dev/null and b/assets/h1_2/meshes/left_hand_link.STL differ
diff --git a/assets/h1_2/meshes/left_hip_pitch_link.STL b/assets/h1_2/meshes/left_hip_pitch_link.STL
new file mode 100644
index 0000000..924c0e5
Binary files /dev/null and b/assets/h1_2/meshes/left_hip_pitch_link.STL differ
diff --git a/assets/h1_2/meshes/left_hip_roll_link.STL b/assets/h1_2/meshes/left_hip_roll_link.STL
new file mode 100644
index 0000000..a9353e9
Binary files /dev/null and b/assets/h1_2/meshes/left_hip_roll_link.STL differ
diff --git a/assets/h1_2/meshes/left_hip_yaw_link.STL b/assets/h1_2/meshes/left_hip_yaw_link.STL
new file mode 100644
index 0000000..2b97fd7
Binary files /dev/null and b/assets/h1_2/meshes/left_hip_yaw_link.STL differ
diff --git a/assets/h1_2/meshes/left_knee_link.STL b/assets/h1_2/meshes/left_knee_link.STL
new file mode 100644
index 0000000..fe89e75
Binary files /dev/null and b/assets/h1_2/meshes/left_knee_link.STL differ
diff --git a/assets/h1_2/meshes/left_shoulder_pitch_link.STL b/assets/h1_2/meshes/left_shoulder_pitch_link.STL
new file mode 100644
index 0000000..23289ce
Binary files /dev/null and b/assets/h1_2/meshes/left_shoulder_pitch_link.STL differ
diff --git a/assets/h1_2/meshes/left_shoulder_roll_link.STL b/assets/h1_2/meshes/left_shoulder_roll_link.STL
new file mode 100644
index 0000000..a28d854
Binary files /dev/null and b/assets/h1_2/meshes/left_shoulder_roll_link.STL differ
diff --git a/assets/h1_2/meshes/left_shoulder_yaw_link.STL b/assets/h1_2/meshes/left_shoulder_yaw_link.STL
new file mode 100644
index 0000000..87cbbbc
Binary files /dev/null and b/assets/h1_2/meshes/left_shoulder_yaw_link.STL differ
diff --git a/assets/h1_2/meshes/left_wrist_pitch_link.STL b/assets/h1_2/meshes/left_wrist_pitch_link.STL
new file mode 100644
index 0000000..83d6d87
Binary files /dev/null and b/assets/h1_2/meshes/left_wrist_pitch_link.STL differ
diff --git a/assets/h1_2/meshes/link11_L.STL b/assets/h1_2/meshes/link11_L.STL
new file mode 100644
index 0000000..9933a6c
Binary files /dev/null and b/assets/h1_2/meshes/link11_L.STL differ
diff --git a/assets/h1_2/meshes/link11_R.STL b/assets/h1_2/meshes/link11_R.STL
new file mode 100644
index 0000000..30817a8
Binary files /dev/null and b/assets/h1_2/meshes/link11_R.STL differ
diff --git a/assets/h1_2/meshes/link12_L.STL b/assets/h1_2/meshes/link12_L.STL
new file mode 100644
index 0000000..08071d3
Binary files /dev/null and b/assets/h1_2/meshes/link12_L.STL differ
diff --git a/assets/h1_2/meshes/link12_R.STL b/assets/h1_2/meshes/link12_R.STL
new file mode 100644
index 0000000..137dbde
Binary files /dev/null and b/assets/h1_2/meshes/link12_R.STL differ
diff --git a/assets/h1_2/meshes/link13_L.STL b/assets/h1_2/meshes/link13_L.STL
new file mode 100644
index 0000000..03a3425
Binary files /dev/null and b/assets/h1_2/meshes/link13_L.STL differ
diff --git a/assets/h1_2/meshes/link13_R.STL b/assets/h1_2/meshes/link13_R.STL
new file mode 100644
index 0000000..a42829f
Binary files /dev/null and b/assets/h1_2/meshes/link13_R.STL differ
diff --git a/assets/h1_2/meshes/link14_L.STL b/assets/h1_2/meshes/link14_L.STL
new file mode 100644
index 0000000..291a14f
Binary files /dev/null and b/assets/h1_2/meshes/link14_L.STL differ
diff --git a/assets/h1_2/meshes/link14_R.STL b/assets/h1_2/meshes/link14_R.STL
new file mode 100644
index 0000000..13f98f8
Binary files /dev/null and b/assets/h1_2/meshes/link14_R.STL differ
diff --git a/assets/h1_2/meshes/link15_L.STL b/assets/h1_2/meshes/link15_L.STL
new file mode 100644
index 0000000..f899431
Binary files /dev/null and b/assets/h1_2/meshes/link15_L.STL differ
diff --git a/assets/h1_2/meshes/link15_R.STL b/assets/h1_2/meshes/link15_R.STL
new file mode 100644
index 0000000..cbfc711
Binary files /dev/null and b/assets/h1_2/meshes/link15_R.STL differ
diff --git a/assets/h1_2/meshes/link16_L.STL b/assets/h1_2/meshes/link16_L.STL
new file mode 100644
index 0000000..24a5a83
Binary files /dev/null and b/assets/h1_2/meshes/link16_L.STL differ
diff --git a/assets/h1_2/meshes/link16_R.STL b/assets/h1_2/meshes/link16_R.STL
new file mode 100644
index 0000000..0cf0f8d
Binary files /dev/null and b/assets/h1_2/meshes/link16_R.STL differ
diff --git a/assets/h1_2/meshes/link17_L.STL b/assets/h1_2/meshes/link17_L.STL
new file mode 100644
index 0000000..8f0aca6
Binary files /dev/null and b/assets/h1_2/meshes/link17_L.STL differ
diff --git a/assets/h1_2/meshes/link17_R.STL b/assets/h1_2/meshes/link17_R.STL
new file mode 100644
index 0000000..3f630a3
Binary files /dev/null and b/assets/h1_2/meshes/link17_R.STL differ
diff --git a/assets/h1_2/meshes/link18_L.STL b/assets/h1_2/meshes/link18_L.STL
new file mode 100644
index 0000000..c498cd7
Binary files /dev/null and b/assets/h1_2/meshes/link18_L.STL differ
diff --git a/assets/h1_2/meshes/link18_R.STL b/assets/h1_2/meshes/link18_R.STL
new file mode 100644
index 0000000..ebc2616
Binary files /dev/null and b/assets/h1_2/meshes/link18_R.STL differ
diff --git a/assets/h1_2/meshes/link19_L.STL b/assets/h1_2/meshes/link19_L.STL
new file mode 100644
index 0000000..c3cabb9
Binary files /dev/null and b/assets/h1_2/meshes/link19_L.STL differ
diff --git a/assets/h1_2/meshes/link19_R.STL b/assets/h1_2/meshes/link19_R.STL
new file mode 100644
index 0000000..5c3703e
Binary files /dev/null and b/assets/h1_2/meshes/link19_R.STL differ
diff --git a/assets/h1_2/meshes/link20_L.STL b/assets/h1_2/meshes/link20_L.STL
new file mode 100644
index 0000000..23c4efa
Binary files /dev/null and b/assets/h1_2/meshes/link20_L.STL differ
diff --git a/assets/h1_2/meshes/link20_R.STL b/assets/h1_2/meshes/link20_R.STL
new file mode 100644
index 0000000..5fed852
Binary files /dev/null and b/assets/h1_2/meshes/link20_R.STL differ
diff --git a/assets/h1_2/meshes/link21_L.STL b/assets/h1_2/meshes/link21_L.STL
new file mode 100644
index 0000000..ccb63bf
Binary files /dev/null and b/assets/h1_2/meshes/link21_L.STL differ
diff --git a/assets/h1_2/meshes/link21_R.STL b/assets/h1_2/meshes/link21_R.STL
new file mode 100644
index 0000000..d4710f1
Binary files /dev/null and b/assets/h1_2/meshes/link21_R.STL differ
diff --git a/assets/h1_2/meshes/link22_L.STL b/assets/h1_2/meshes/link22_L.STL
new file mode 100644
index 0000000..6b9cdad
Binary files /dev/null and b/assets/h1_2/meshes/link22_L.STL differ
diff --git a/assets/h1_2/meshes/link22_R.STL b/assets/h1_2/meshes/link22_R.STL
new file mode 100644
index 0000000..c2cf58b
Binary files /dev/null and b/assets/h1_2/meshes/link22_R.STL differ
diff --git a/assets/h1_2/meshes/logo_link.STL b/assets/h1_2/meshes/logo_link.STL
new file mode 100644
index 0000000..c396d51
Binary files /dev/null and b/assets/h1_2/meshes/logo_link.STL differ
diff --git a/assets/h1_2/meshes/pelvis.STL b/assets/h1_2/meshes/pelvis.STL
new file mode 100644
index 0000000..05e5512
Binary files /dev/null and b/assets/h1_2/meshes/pelvis.STL differ
diff --git a/assets/h1_2/meshes/right_ankle_A_link.STL b/assets/h1_2/meshes/right_ankle_A_link.STL
new file mode 100644
index 0000000..2ed1eaf
Binary files /dev/null and b/assets/h1_2/meshes/right_ankle_A_link.STL differ
diff --git a/assets/h1_2/meshes/right_ankle_A_rod_link.STL b/assets/h1_2/meshes/right_ankle_A_rod_link.STL
new file mode 100644
index 0000000..1fc9acc
Binary files /dev/null and b/assets/h1_2/meshes/right_ankle_A_rod_link.STL differ
diff --git a/assets/h1_2/meshes/right_ankle_B_link.STL b/assets/h1_2/meshes/right_ankle_B_link.STL
new file mode 100644
index 0000000..6563110
Binary files /dev/null and b/assets/h1_2/meshes/right_ankle_B_link.STL differ
diff --git a/assets/h1_2/meshes/right_ankle_B_rod_link.STL b/assets/h1_2/meshes/right_ankle_B_rod_link.STL
new file mode 100644
index 0000000..bdaa919
Binary files /dev/null and b/assets/h1_2/meshes/right_ankle_B_rod_link.STL differ
diff --git a/assets/h1_2/meshes/right_ankle_link.STL b/assets/h1_2/meshes/right_ankle_link.STL
new file mode 100644
index 0000000..7045cea
Binary files /dev/null and b/assets/h1_2/meshes/right_ankle_link.STL differ
diff --git a/assets/h1_2/meshes/right_ankle_pitch_link.STL b/assets/h1_2/meshes/right_ankle_pitch_link.STL
new file mode 100644
index 0000000..827fb2c
Binary files /dev/null and b/assets/h1_2/meshes/right_ankle_pitch_link.STL differ
diff --git a/assets/h1_2/meshes/right_ankle_roll_link.STL b/assets/h1_2/meshes/right_ankle_roll_link.STL
new file mode 100644
index 0000000..5fe6027
Binary files /dev/null and b/assets/h1_2/meshes/right_ankle_roll_link.STL differ
diff --git a/assets/h1_2/meshes/right_elbow_pitch_link.STL b/assets/h1_2/meshes/right_elbow_pitch_link.STL
new file mode 100644
index 0000000..70bf14d
Binary files /dev/null and b/assets/h1_2/meshes/right_elbow_pitch_link.STL differ
diff --git a/assets/h1_2/meshes/right_elbow_roll_link.STL b/assets/h1_2/meshes/right_elbow_roll_link.STL
new file mode 100644
index 0000000..5f7f228
Binary files /dev/null and b/assets/h1_2/meshes/right_elbow_roll_link.STL differ
diff --git a/assets/h1_2/meshes/right_hand_link.STL b/assets/h1_2/meshes/right_hand_link.STL
new file mode 100644
index 0000000..6ce2dcf
Binary files /dev/null and b/assets/h1_2/meshes/right_hand_link.STL differ
diff --git a/assets/h1_2/meshes/right_hip_pitch_link.STL b/assets/h1_2/meshes/right_hip_pitch_link.STL
new file mode 100644
index 0000000..aa0b4c2
Binary files /dev/null and b/assets/h1_2/meshes/right_hip_pitch_link.STL differ
diff --git a/assets/h1_2/meshes/right_hip_roll_link.STL b/assets/h1_2/meshes/right_hip_roll_link.STL
new file mode 100644
index 0000000..6032b95
Binary files /dev/null and b/assets/h1_2/meshes/right_hip_roll_link.STL differ
diff --git a/assets/h1_2/meshes/right_hip_yaw_link.STL b/assets/h1_2/meshes/right_hip_yaw_link.STL
new file mode 100644
index 0000000..5039005
Binary files /dev/null and b/assets/h1_2/meshes/right_hip_yaw_link.STL differ
diff --git a/assets/h1_2/meshes/right_knee_link.STL b/assets/h1_2/meshes/right_knee_link.STL
new file mode 100644
index 0000000..fe89e75
Binary files /dev/null and b/assets/h1_2/meshes/right_knee_link.STL differ
diff --git a/assets/h1_2/meshes/right_pitch_link.STL b/assets/h1_2/meshes/right_pitch_link.STL
new file mode 100644
index 0000000..f5276e9
Binary files /dev/null and b/assets/h1_2/meshes/right_pitch_link.STL differ
diff --git a/assets/h1_2/meshes/right_shoulder_pitch_link.STL b/assets/h1_2/meshes/right_shoulder_pitch_link.STL
new file mode 100644
index 0000000..87974a3
Binary files /dev/null and b/assets/h1_2/meshes/right_shoulder_pitch_link.STL differ
diff --git a/assets/h1_2/meshes/right_shoulder_roll_link.STL b/assets/h1_2/meshes/right_shoulder_roll_link.STL
new file mode 100644
index 0000000..cf9bfb5
Binary files /dev/null and b/assets/h1_2/meshes/right_shoulder_roll_link.STL differ
diff --git a/assets/h1_2/meshes/right_shoulder_yaw_link.STL b/assets/h1_2/meshes/right_shoulder_yaw_link.STL
new file mode 100644
index 0000000..701f379
Binary files /dev/null and b/assets/h1_2/meshes/right_shoulder_yaw_link.STL differ
diff --git a/assets/h1_2/meshes/right_wrist_pitch_link.STL b/assets/h1_2/meshes/right_wrist_pitch_link.STL
new file mode 100644
index 0000000..f21d1f0
Binary files /dev/null and b/assets/h1_2/meshes/right_wrist_pitch_link.STL differ
diff --git a/assets/h1_2/meshes/torso_link.STL b/assets/h1_2/meshes/torso_link.STL
new file mode 100644
index 0000000..37e1f60
Binary files /dev/null and b/assets/h1_2/meshes/torso_link.STL differ
diff --git a/assets/h1_2/meshes/wrist_yaw_link.STL b/assets/h1_2/meshes/wrist_yaw_link.STL
new file mode 100644
index 0000000..90643cf
Binary files /dev/null and b/assets/h1_2/meshes/wrist_yaw_link.STL differ
diff --git a/assets/h1_2/scene.xml b/assets/h1_2/scene.xml
new file mode 100644
index 0000000..c2375fe
--- /dev/null
+++ b/assets/h1_2/scene.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/teleop/image_server/image_server.py b/teleop/image_server/image_server.py
index 8328210..fa542ff 100644
--- a/teleop/image_server/image_server.py
+++ b/teleop/image_server/image_server.py
@@ -102,7 +102,7 @@ class OpenCVCamera():
class ImageServer:
def __init__(self, config, port = 5555, Unit_Test = False):
"""
- config:
+ config example1:
{
'fps':30 # frame per second
'head_camera_type': 'opencv', # opencv or realsense
@@ -110,7 +110,30 @@ class ImageServer:
'head_camera_id_numbers': [0], # '/dev/video0' (opencv)
'wrist_camera_type': 'realsense',
'wrist_camera_image_shape': [480, 640], # Wrist camera resolution [height, width]
- 'wrist_camera_id_numbers': ["218622271789", "241222076627"], # serial number (realsense)
+ 'wrist_camera_id_numbers': ["218622271789", "241222076627"], # realsense camera's serial number
+ }
+
+ config example2:
+ {
+ 'fps':30 # frame per second
+ 'head_camera_type': 'realsense', # opencv or realsense
+ 'head_camera_image_shape': [480, 640], # Head camera resolution [height, width]
+ 'head_camera_id_numbers': ["218622271739"], # realsense camera's serial number
+ 'wrist_camera_type': 'opencv',
+ 'wrist_camera_image_shape': [480, 640], # Wrist camera resolution [height, width]
+ 'wrist_camera_id_numbers': [0,1], # '/dev/video0' and '/dev/video1' (opencv)
+ }
+
+ If you are not using the wrist camera, you can comment out its configuration, like this below:
+ config:
+ {
+ 'fps':30 # frame per second
+ 'head_camera_type': 'opencv', # opencv or realsense
+ 'head_camera_image_shape': [480, 1280], # Head camera resolution [height, width]
+ 'head_camera_id_numbers': [0], # '/dev/video0' (opencv)
+ #'wrist_camera_type': 'realsense',
+ #'wrist_camera_image_shape': [480, 640], # Wrist camera resolution [height, width]
+ #'wrist_camera_id_numbers': ["218622271789", "241222076627"], # serial number (realsense)
}
"""
print(config)
diff --git a/teleop/robot_control/robot_arm.py b/teleop/robot_control/robot_arm.py
index 13f3c5c..3443e95 100644
--- a/teleop/robot_control/robot_arm.py
+++ b/teleop/robot_control/robot_arm.py
@@ -11,6 +11,7 @@ from unitree_sdk2py.utils.crc import CRC
kTopicLowCommand = "rt/lowcmd"
kTopicLowState = "rt/lowstate"
G1_29_Num_Motors = 35
+H1_2_Num_Motors = 35
class MotorState:
@@ -22,6 +23,9 @@ class G1_29_LowState:
def __init__(self):
self.motor_state = [MotorState() for _ in range(G1_29_Num_Motors)]
+class H1_2_LowState:
+ def __init__(self):
+ self.motor_state = [MotorState() for _ in range(H1_2_Num_Motors)]
class DataBuffer:
def __init__(self):
self.data = None
@@ -299,12 +303,277 @@ class G1_29_JointIndex(IntEnum):
kNotUsedJoint4 = 33
kNotUsedJoint5 = 34
+class H1_2_ArmController:
+ def __init__(self):
+ print("Initialize H1_2_ArmController...")
+ self.q_target = np.zeros(14)
+ self.tauff_target = np.zeros(14)
+
+ self.kp_high = 200.0
+ self.kd_high = 5.0
+ self.kp_low = 140.0
+ self.kd_low = 7.5
+ self.kp_wrist = 40.0
+ self.kd_wrist = 6.0
+
+ self.all_motor_q = None
+ self.arm_velocity_limit = 20.0
+ self.control_dt = 1.0 / 250.0
+
+ self._speed_gradual_max = False
+ self._gradual_start_time = None
+ self._gradual_time = None
+
+ # initialize lowcmd publisher and lowstate subscriber
+ ChannelFactoryInitialize(0)
+ self.lowcmd_publisher = ChannelPublisher(kTopicLowCommand, LowCmd_)
+ self.lowcmd_publisher.Init()
+ self.lowstate_subscriber = ChannelSubscriber(kTopicLowState, LowState_)
+ self.lowstate_subscriber.Init()
+ self.lowstate_buffer = DataBuffer()
+
+ # initialize subscribe thread
+ self.subscribe_thread = threading.Thread(target=self._subscribe_motor_state)
+ self.subscribe_thread.daemon = True
+ self.subscribe_thread.start()
+
+ while not self.lowstate_buffer.GetData():
+ time.sleep(0.01)
+ print("[H1_2_ArmController] Waiting to subscribe dds...")
+
+ # initialize hg's lowcmd msg
+ self.crc = CRC()
+ self.msg = unitree_hg_msg_dds__LowCmd_()
+ self.msg.mode_pr = 0
+ self.msg.mode_machine = self.get_mode_machine()
+
+ self.all_motor_q = self.get_current_motor_q()
+ print(f"Current all body motor state q:\n{self.all_motor_q} \n")
+ print(f"Current two arms motor state q:\n{self.get_current_dual_arm_q()}\n")
+ print("Lock all joints except two arms...\n")
+
+ arm_indices = set(member.value for member in H1_2_JointArmIndex)
+ for id in H1_2_JointIndex:
+ self.msg.motor_cmd[id].mode = 1
+ if id.value in arm_indices:
+ if self._Is_wrist_motor(id):
+ self.msg.motor_cmd[id].kp = self.kp_wrist
+ self.msg.motor_cmd[id].kd = self.kd_wrist
+ else:
+ self.msg.motor_cmd[id].kp = self.kp_low
+ self.msg.motor_cmd[id].kd = self.kd_low
+ else:
+ if self._Is_weak_motor(id):
+ self.msg.motor_cmd[id].kp = self.kp_low
+ self.msg.motor_cmd[id].kd = self.kd_low
+ else:
+ self.msg.motor_cmd[id].kp = self.kp_high
+ self.msg.motor_cmd[id].kd = self.kd_high
+ self.msg.motor_cmd[id].q = self.all_motor_q[id]
+ print("Lock OK!\n")
+
+ # initialize publish thread
+ self.publish_thread = threading.Thread(target=self._ctrl_motor_state)
+ self.ctrl_lock = threading.Lock()
+ self.publish_thread.daemon = True
+ self.publish_thread.start()
+
+ print("Initialize H1_2_ArmController OK!\n")
+
+ def _subscribe_motor_state(self):
+ while True:
+ msg = self.lowstate_subscriber.Read()
+ if msg is not None:
+ lowstate = H1_2_LowState()
+ for id in range(H1_2_Num_Motors):
+ lowstate.motor_state[id].q = msg.motor_state[id].q
+ lowstate.motor_state[id].dq = msg.motor_state[id].dq
+ self.lowstate_buffer.SetData(lowstate)
+ time.sleep(0.002)
+
+ def clip_arm_q_target(self, target_q, velocity_limit):
+ current_q = self.get_current_dual_arm_q()
+ delta = target_q - current_q
+ motion_scale = np.max(np.abs(delta)) / (velocity_limit * self.control_dt)
+ cliped_arm_q_target = current_q + delta / max(motion_scale, 1.0)
+ return cliped_arm_q_target
+
+ def _ctrl_motor_state(self):
+ while True:
+ start_time = time.time()
+
+ with self.ctrl_lock:
+ arm_q_target = self.q_target
+ arm_tauff_target = self.tauff_target
+
+ cliped_arm_q_target = self.clip_arm_q_target(arm_q_target, velocity_limit = self.arm_velocity_limit)
+
+ for idx, id in enumerate(G1_29_JointArmIndex):
+ self.msg.motor_cmd[id].q = cliped_arm_q_target[idx]
+ self.msg.motor_cmd[id].dq = 0
+ self.msg.motor_cmd[id].tau = arm_tauff_target[idx]
+
+ self.msg.crc = self.crc.Crc(self.msg)
+ self.lowcmd_publisher.Write(self.msg)
+
+ if self._speed_gradual_max is True:
+ t_elapsed = start_time - self._gradual_start_time
+ self.arm_velocity_limit = 20.0 + (10.0 * min(1.0, t_elapsed / 5.0))
+
+ current_time = time.time()
+ all_t_elapsed = current_time - start_time
+ sleep_time = max(0, (self.control_dt - all_t_elapsed))
+ time.sleep(sleep_time)
+ # print(f"arm_velocity_limit:{self.arm_velocity_limit}")
+ # print(f"sleep_time:{sleep_time}")
+
+ def ctrl_dual_arm(self, q_target, tauff_target):
+ '''Set control target values q & tau of the left and right arm motors.'''
+ with self.ctrl_lock:
+ self.q_target = q_target
+ self.tauff_target = tauff_target
+
+ def get_mode_machine(self):
+ '''Return current dds mode machine.'''
+ return self.lowstate_subscriber.Read().mode_machine
+
+ def get_current_motor_q(self):
+ '''Return current state q of all body motors.'''
+ return np.array([self.lowstate_buffer.GetData().motor_state[id].q for id in H1_2_JointIndex])
+
+ def get_current_dual_arm_q(self):
+ '''Return current state q of the left and right arm motors.'''
+ return np.array([self.lowstate_buffer.GetData().motor_state[id].q for id in H1_2_JointArmIndex])
+
+ def get_current_dual_arm_dq(self):
+ '''Return current state dq of the left and right arm motors.'''
+ return np.array([self.lowstate_buffer.GetData().motor_state[id].dq for id in H1_2_JointArmIndex])
+
+ def ctrl_dual_arm_go_home(self):
+ '''Move both the left and right arms of the robot to their home position by setting the target joint angles (q) and torques (tau) to zero.'''
+ print("[H1_2_ArmController] ctrl_dual_arm_go_home start...")
+ with self.ctrl_lock:
+ self.q_target = np.zeros(14)
+ # self.tauff_target = np.zeros(14)
+ tolerance = 0.05 # Tolerance threshold for joint angles to determine "close to zero", can be adjusted based on your motor's precision requirements
+ while True:
+ current_q = self.get_current_dual_arm_q()
+ if np.all(np.abs(current_q) < tolerance):
+ print("[H1_2_ArmController] both arms have reached the home position.")
+ break
+ time.sleep(0.05)
+
+ def speed_gradual_max(self, t = 5.0):
+ '''Parameter t is the total time required for arms velocity to gradually increase to its maximum value, in seconds. The default is 5.0.'''
+ self._gradual_start_time = time.time()
+ self._gradual_time = t
+ self._speed_gradual_max = True
+
+ def speed_instant_max(self):
+ '''set arms velocity to the maximum value immediately, instead of gradually increasing.'''
+ self.arm_velocity_limit = 30.0
+
+ def _Is_weak_motor(self, motor_index):
+ weak_motors = [
+ H1_2_JointIndex.kLeftAnkle.value,
+ H1_2_JointIndex.kRightAnkle.value,
+ # Left arm
+ H1_2_JointIndex.kLeftShoulderPitch.value,
+ H1_2_JointIndex.kLeftShoulderRoll.value,
+ H1_2_JointIndex.kLeftShoulderYaw.value,
+ H1_2_JointIndex.kLeftElbowPitch.value,
+ # Right arm
+ H1_2_JointIndex.kRightShoulderPitch.value,
+ H1_2_JointIndex.kRightShoulderRoll.value,
+ H1_2_JointIndex.kRightShoulderYaw.value,
+ H1_2_JointIndex.kRightElbowPitch.value,
+ ]
+ return motor_index.value in weak_motors
+
+ def _Is_wrist_motor(self, motor_index):
+ wrist_motors = [
+ H1_2_JointIndex.kLeftElbowRoll.value,
+ H1_2_JointIndex.kLeftWristPitch.value,
+ H1_2_JointIndex.kLeftWristyaw.value,
+ H1_2_JointIndex.kRightElbowRoll.value,
+ H1_2_JointIndex.kRightWristPitch.value,
+ H1_2_JointIndex.kRightWristYaw.value,
+ ]
+ return motor_index.value in wrist_motors
+
+class H1_2_JointArmIndex(IntEnum):
+ # Left arm
+ kLeftShoulderPitch = 13
+ kLeftShoulderRoll = 14
+ kLeftShoulderYaw = 15
+ kLeftElbowPitch = 16
+ kLeftElbowRoll = 17
+ kLeftWristPitch = 18
+ kLeftWristyaw = 19
+
+ # Right arm
+ kRightShoulderPitch = 20
+ kRightShoulderRoll = 21
+ kRightShoulderYaw = 22
+ kRightElbowPitch = 23
+ kRightElbowRoll = 24
+ kRightWristPitch = 25
+ kRightWristYaw = 26
+
+class H1_2_JointIndex(IntEnum):
+ # Left leg
+ kLeftHipYaw = 0
+ kLeftHipRoll = 1
+ kLeftHipPitch = 2
+ kLeftKnee = 3
+ kLeftAnkle = 4
+ kLeftAnkleRoll = 5
+
+ # Right leg
+ kRightHipYaw = 6
+ kRightHipRoll = 7
+ kRightHipPitch = 8
+ kRightKnee = 9
+ kRightAnkle = 10
+ kRightAnkleRoll = 11
+
+ kWaistYaw = 12
+
+ # Left arm
+ kLeftShoulderPitch = 13
+ kLeftShoulderRoll = 14
+ kLeftShoulderYaw = 15
+ kLeftElbowPitch = 16
+ kLeftElbowRoll = 17
+ kLeftWristPitch = 18
+ kLeftWristyaw = 19
+
+ # Right arm
+ kRightShoulderPitch = 20
+ kRightShoulderRoll = 21
+ kRightShoulderYaw = 22
+ kRightElbowPitch = 23
+ kRightElbowRoll = 24
+ kRightWristPitch = 25
+ kRightWristYaw = 26
+
+ kNotUsedJoint0 = 27
+ kNotUsedJoint1 = 28
+ kNotUsedJoint2 = 29
+ kNotUsedJoint3 = 30
+ kNotUsedJoint4 = 31
+ kNotUsedJoint5 = 32
+ kNotUsedJoint6 = 33
+ kNotUsedJoint7 = 34
+
if __name__ == "__main__":
- from robot_arm_ik import G1_29_ArmIK
+ from robot_arm_ik import G1_29_ArmIK, H1_2_ArmIK
import pinocchio as pin
- arm_ik = G1_29_ArmIK(Unit_Test = True, Visualization = False)
- g1arm = G1_29_ArmController()
+ # arm_ik = G1_29_ArmIK(Unit_Test = True, Visualization = False)
+ # arm = G1_29_ArmController()
+ arm_ik = H1_2_ArmIK(Unit_Test = True, Visualization = False)
+ arm = H1_2_ArmController()
# initial positon
L_tf_target = pin.SE3(
@@ -324,7 +593,7 @@ if __name__ == "__main__":
user_input = input("Please enter the start signal (enter 's' to start the subsequent program): \n")
if user_input.lower() == 's':
step = 0
- g1arm.speed_gradual_max()
+ arm.speed_gradual_max()
while True:
if step <= 120:
angle = rotation_speed * step
@@ -344,12 +613,12 @@ if __name__ == "__main__":
L_tf_target.rotation = L_quat.toRotationMatrix()
R_tf_target.rotation = R_quat.toRotationMatrix()
- current_lr_arm_q = g1arm.get_current_dual_arm_q()
- current_lr_arm_dq = g1arm.get_current_dual_arm_dq()
+ current_lr_arm_q = arm.get_current_dual_arm_q()
+ current_lr_arm_dq = arm.get_current_dual_arm_dq()
sol_q, sol_tauff = arm_ik.solve_ik(L_tf_target.homogeneous, R_tf_target.homogeneous, current_lr_arm_q, current_lr_arm_dq)
- g1arm.ctrl_dual_arm(sol_q, sol_tauff)
+ arm.ctrl_dual_arm(sol_q, sol_tauff)
step += 1
if step > 240:
diff --git a/teleop/robot_control/robot_arm_ik.py b/teleop/robot_control/robot_arm_ik.py
index 601a96b..8d1392f 100644
--- a/teleop/robot_control/robot_arm_ik.py
+++ b/teleop/robot_control/robot_arm_ik.py
@@ -258,9 +258,260 @@ class G1_29_ArmIK:
# return sol_q, sol_tauff
return current_lr_arm_motor_q, np.zeros(self.reduced_robot.model.nv)
+class H1_2_ArmIK:
+ def __init__(self, Unit_Test = False, Visualization = False):
+ np.set_printoptions(precision=5, suppress=True, linewidth=200)
+
+ self.Unit_Test = Unit_Test
+ self.Visualization = Visualization
+
+ if not self.Unit_Test:
+ self.robot = pin.RobotWrapper.BuildFromURDF('../assets/h1_2/h1_2.urdf', '../assets/h1_2/')
+ else:
+ self.robot = pin.RobotWrapper.BuildFromURDF('../../assets/h1_2/h1_2.urdf', '../../assets/h1_2/') # for test
+
+ self.mixed_jointsToLockIDs = [
+ "left_hip_yaw_joint",
+ "left_hip_pitch_joint",
+ "left_hip_roll_joint",
+ "left_knee_joint",
+ "left_ankle_pitch_joint",
+ "left_ankle_roll_joint",
+ "right_hip_yaw_joint",
+ "right_hip_pitch_joint",
+ "right_hip_roll_joint",
+ "right_knee_joint",
+ "right_ankle_pitch_joint",
+ "right_ankle_roll_joint",
+ "torso_joint",
+ "L_index_proximal_joint",
+ "L_index_intermediate_joint",
+ "L_middle_proximal_joint",
+ "L_middle_intermediate_joint",
+ "L_pinky_proximal_joint",
+ "L_pinky_intermediate_joint",
+ "L_ring_proximal_joint",
+ "L_ring_intermediate_joint",
+ "L_thumb_proximal_yaw_joint",
+ "L_thumb_proximal_pitch_joint",
+ "L_thumb_intermediate_joint",
+ "L_thumb_distal_joint",
+ "R_index_proximal_joint",
+ "R_index_intermediate_joint",
+ "R_middle_proximal_joint",
+ "R_middle_intermediate_joint",
+ "R_pinky_proximal_joint",
+ "R_pinky_intermediate_joint",
+ "R_ring_proximal_joint",
+ "R_ring_intermediate_joint",
+ "R_thumb_proximal_yaw_joint",
+ "R_thumb_proximal_pitch_joint",
+ "R_thumb_intermediate_joint",
+ "R_thumb_distal_joint"
+ ]
+
+ self.reduced_robot = self.robot.buildReducedRobot(
+ list_of_joints_to_lock=self.mixed_jointsToLockIDs,
+ reference_configuration=np.array([0.0] * self.robot.model.nq),
+ )
+
+ self.reduced_robot.model.addFrame(
+ pin.Frame('L_ee',
+ self.reduced_robot.model.getJointId('left_wrist_yaw_joint'),
+ pin.SE3(np.eye(3),
+ np.array([0.05,0,0]).T),
+ pin.FrameType.OP_FRAME)
+ )
+
+ self.reduced_robot.model.addFrame(
+ pin.Frame('R_ee',
+ self.reduced_robot.model.getJointId('right_wrist_yaw_joint'),
+ pin.SE3(np.eye(3),
+ np.array([0.05,0,0]).T),
+ pin.FrameType.OP_FRAME)
+ )
+
+ # for i in range(self.reduced_robot.model.nframes):
+ # frame = self.reduced_robot.model.frames[i]
+ # frame_id = self.reduced_robot.model.getFrameId(frame.name)
+ # print(f"Frame ID: {frame_id}, Name: {frame.name}")
+
+ # Creating Casadi models and data for symbolic computing
+ self.cmodel = cpin.Model(self.reduced_robot.model)
+ self.cdata = self.cmodel.createData()
+
+ # Creating symbolic variables
+ self.cq = casadi.SX.sym("q", self.reduced_robot.model.nq, 1)
+ self.cTf_l = casadi.SX.sym("tf_l", 4, 4)
+ self.cTf_r = casadi.SX.sym("tf_r", 4, 4)
+ cpin.framesForwardKinematics(self.cmodel, self.cdata, self.cq)
+
+ # Get the hand joint ID and define the error function
+ self.L_hand_id = self.reduced_robot.model.getFrameId("L_ee")
+ self.R_hand_id = self.reduced_robot.model.getFrameId("R_ee")
+
+ self.translational_error = casadi.Function(
+ "translational_error",
+ [self.cq, self.cTf_l, self.cTf_r],
+ [
+ casadi.vertcat(
+ self.cdata.oMf[self.L_hand_id].translation - self.cTf_l[:3,3],
+ self.cdata.oMf[self.R_hand_id].translation - self.cTf_r[:3,3]
+ )
+ ],
+ )
+ self.rotational_error = casadi.Function(
+ "rotational_error",
+ [self.cq, self.cTf_l, self.cTf_r],
+ [
+ casadi.vertcat(
+ cpin.log3(self.cdata.oMf[self.L_hand_id].rotation @ self.cTf_l[:3,:3].T),
+ cpin.log3(self.cdata.oMf[self.R_hand_id].rotation @ self.cTf_r[:3,:3].T)
+ )
+ ],
+ )
+
+ # Defining the optimization problem
+ self.opti = casadi.Opti()
+ self.var_q = self.opti.variable(self.reduced_robot.model.nq)
+ self.var_q_last = self.opti.parameter(self.reduced_robot.model.nq) # for smooth
+ self.param_tf_l = self.opti.parameter(4, 4)
+ self.param_tf_r = self.opti.parameter(4, 4)
+ self.translational_cost = casadi.sumsqr(self.translational_error(self.var_q, self.param_tf_l, self.param_tf_r))
+ self.rotation_cost = casadi.sumsqr(self.rotational_error(self.var_q, self.param_tf_l, self.param_tf_r))
+ self.regularization_cost = casadi.sumsqr(self.var_q)
+ self.smooth_cost = casadi.sumsqr(self.var_q - self.var_q_last)
+
+ # Setting optimization constraints and goals
+ self.opti.subject_to(self.opti.bounded(
+ self.reduced_robot.model.lowerPositionLimit,
+ self.var_q,
+ self.reduced_robot.model.upperPositionLimit)
+ )
+ self.opti.minimize(50 * self.translational_cost + self.rotation_cost + 0.02 * self.regularization_cost + 0.1 * self.smooth_cost)
+
+ opts = {
+ 'ipopt':{
+ 'print_level':0,
+ 'max_iter':50,
+ 'tol':1e-6
+ },
+ 'print_time':False,# print or not
+ 'calc_lam_p':False # https://github.com/casadi/casadi/wiki/FAQ:-Why-am-I-getting-%22NaN-detected%22in-my-optimization%3F
+ }
+ self.opti.solver("ipopt", opts)
+
+ self.init_data = np.zeros(self.reduced_robot.model.nq)
+ self.smooth_filter = WeightedMovingFilter(np.array([0.4, 0.3, 0.2, 0.1]), 14)
+ self.vis = None
+
+ if self.Visualization:
+ # Initialize the Meshcat visualizer for visualization
+ self.vis = MeshcatVisualizer(self.reduced_robot.model, self.reduced_robot.collision_model, self.reduced_robot.visual_model)
+ self.vis.initViewer(open=True)
+ self.vis.loadViewerModel("pinocchio")
+ self.vis.displayFrames(True, frame_ids=[101, 102], axis_length = 0.15, axis_width = 5)
+ self.vis.display(pin.neutral(self.reduced_robot.model))
+
+ # Enable the display of end effector target frames with short axis lengths and greater width.
+ frame_viz_names = ['L_ee_target', 'R_ee_target']
+ FRAME_AXIS_POSITIONS = (
+ np.array([[0, 0, 0], [1, 0, 0],
+ [0, 0, 0], [0, 1, 0],
+ [0, 0, 0], [0, 0, 1]]).astype(np.float32).T
+ )
+ FRAME_AXIS_COLORS = (
+ np.array([[1, 0, 0], [1, 0.6, 0],
+ [0, 1, 0], [0.6, 1, 0],
+ [0, 0, 1], [0, 0.6, 1]]).astype(np.float32).T
+ )
+ axis_length = 0.1
+ axis_width = 10
+ for frame_viz_name in frame_viz_names:
+ self.vis.viewer[frame_viz_name].set_object(
+ mg.LineSegments(
+ mg.PointsGeometry(
+ position=axis_length * FRAME_AXIS_POSITIONS,
+ color=FRAME_AXIS_COLORS,
+ ),
+ mg.LineBasicMaterial(
+ linewidth=axis_width,
+ vertexColors=True,
+ ),
+ )
+ )
+ # If the robot arm is not the same size as your arm :)
+ def scale_arms(self, human_left_pose, human_right_pose, human_arm_length=0.60, robot_arm_length=0.75):
+ scale_factor = robot_arm_length / human_arm_length
+ robot_left_pose = human_left_pose.copy()
+ robot_right_pose = human_right_pose.copy()
+ robot_left_pose[:3, 3] *= scale_factor
+ robot_right_pose[:3, 3] *= scale_factor
+ return robot_left_pose, robot_right_pose
+
+ def solve_ik(self, left_wrist, right_wrist, current_lr_arm_motor_q = None, current_lr_arm_motor_dq = None):
+ if current_lr_arm_motor_q is not None:
+ self.init_data = current_lr_arm_motor_q
+ self.opti.set_initial(self.var_q, self.init_data)
+
+ left_wrist, right_wrist = self.scale_arms(left_wrist, right_wrist)
+ if self.Visualization:
+ self.vis.viewer['L_ee_target'].set_transform(left_wrist) # for visualization
+ self.vis.viewer['R_ee_target'].set_transform(right_wrist) # for visualization
+
+ self.opti.set_value(self.param_tf_l, left_wrist)
+ self.opti.set_value(self.param_tf_r, right_wrist)
+ self.opti.set_value(self.var_q_last, self.init_data) # for smooth
+
+ try:
+ sol = self.opti.solve()
+ # sol = self.opti.solve_limited()
+
+ sol_q = self.opti.value(self.var_q)
+ self.smooth_filter.add_data(sol_q)
+ sol_q = self.smooth_filter.filtered_data
+
+ if current_lr_arm_motor_dq is not None:
+ v = current_lr_arm_motor_dq * 0.0
+ else:
+ v = (sol_q - self.init_data) * 0.0
+
+ self.init_data = sol_q
+
+ sol_tauff = pin.rnea(self.reduced_robot.model, self.reduced_robot.data, sol_q, v, np.zeros(self.reduced_robot.model.nv))
+
+ if self.Visualization:
+ self.vis.display(sol_q) # for visualization
+
+ return sol_q, sol_tauff
+
+ except Exception as e:
+ print(f"ERROR in convergence, plotting debug info.{e}")
+
+ sol_q = self.opti.debug.value(self.var_q)
+ self.smooth_filter.add_data(sol_q)
+ sol_q = self.smooth_filter.filtered_data
+
+ if current_lr_arm_motor_dq is not None:
+ v = current_lr_arm_motor_dq * 0.0
+ else:
+ v = (sol_q - self.init_data) * 0.0
+
+ self.init_data = sol_q
+
+ sol_tauff = pin.rnea(self.reduced_robot.model, self.reduced_robot.data, sol_q, v, np.zeros(self.reduced_robot.model.nv))
+
+ print(f"sol_q:{sol_q} \nmotorstate: \n{current_lr_arm_motor_q} \nleft_pose: \n{left_wrist} \nright_pose: \n{right_wrist}")
+ if self.Visualization:
+ self.vis.display(sol_q) # for visualization
+
+ # return sol_q, sol_tauff
+ return current_lr_arm_motor_q, np.zeros(self.reduced_robot.model.nv)
+
if __name__ == "__main__":
- arm_ik = G1_29_ArmIK(Unit_Test = True, Visualization = True)
+ # arm_ik = G1_29_ArmIK(Unit_Test = True, Visualization = True)
+ arm_ik = H1_2_ArmIK(Unit_Test = True, Visualization = True)
# initial positon
L_tf_target = pin.SE3(
diff --git a/teleop/teleop_hand_and_arm.py b/teleop/teleop_hand_and_arm.py
index 40535f8..8fb7c52 100644
--- a/teleop/teleop_hand_and_arm.py
+++ b/teleop/teleop_hand_and_arm.py
@@ -12,8 +12,8 @@ parent_dir = os.path.dirname(current_dir)
sys.path.append(parent_dir)
from teleop.open_television.tv_wrapper import TeleVisionWrapper
-from teleop.robot_control.robot_arm import G1_29_ArmController
-from teleop.robot_control.robot_arm_ik import G1_29_ArmIK
+from teleop.robot_control.robot_arm import G1_29_ArmController, H1_2_ArmController
+from teleop.robot_control.robot_arm_ik import G1_29_ArmIK, H1_2_ArmIK
from teleop.robot_control.robot_hand_unitree import Dex3_1_Controller, Gripper_Controller
from teleop.image_server.image_client import ImageClient
from teleop.utils.episode_writer import EpisodeWriter
@@ -28,13 +28,14 @@ if __name__ == '__main__':
parser.add_argument('--no-record', dest = 'record', action = 'store_false', help = 'Do not save data')
parser.set_defaults(record = False)
- parser.add_argument('--dex', action='store_true', help='Use dex3-1 hand')
- parser.add_argument('--gripper', dest='dex', action='store_false', help='Use gripper')
- parser.set_defaults(dex = True)
+ parser.add_argument('--arm', type=str, choices=['G1_29', 'H1_2'], default='G1_29', help='Select arm controller')
+
+ parser.add_argument('--hand', type=str, choices=['dex3', 'gripper', 'inspire1'], help='Select hand controller')
+
args = parser.parse_args()
print(f"args:{args}\n")
- # image
+ # image client: img_config should be the same as the configuration in image_server.py (of Robot's development computing unit)
img_config = {
'fps': 30,
'head_camera_type': 'opencv',
@@ -75,26 +76,37 @@ if __name__ == '__main__':
image_receive_thread.daemon = True
image_receive_thread.start()
- # television and arm
+ # television: obtain hand pose data from the XR device and transmit the robot's head camera image to the XR device.
tv_wrapper = TeleVisionWrapper(BINOCULAR, tv_img_shape, tv_img_shm.name)
- arm_ctrl = G1_29_ArmController()
- arm_ik = G1_29_ArmIK()
+
+ # arm
+ if args.arm == 'G1_29':
+ arm_ctrl = G1_29_ArmController()
+ arm_ik = G1_29_ArmIK()
+ elif args.arm == 'H1_2':
+ arm_ctrl = H1_2_ArmController()
+ arm_ik = H1_2_ArmIK()
# hand
- if args.dex:
+ if args.hand == "dex3":
left_hand_array = Array('d', 75, lock = True) # [input]
right_hand_array = Array('d', 75, lock = True) # [input]
dual_hand_data_lock = Lock()
dual_hand_state_array = Array('d', 14, lock = False) # [output] current left, right hand state(14) data.
dual_hand_action_array = Array('d', 14, lock = False) # [output] current left, right hand action(14) data.
hand_ctrl = Dex3_1_Controller(left_hand_array, right_hand_array, dual_hand_data_lock, dual_hand_state_array, dual_hand_action_array)
- else:
+ elif args.hand == "gripper":
left_hand_array = Array('d', 75, lock=True)
right_hand_array = Array('d', 75, lock=True)
dual_gripper_data_lock = Lock()
dual_gripper_state_array = Array('d', 2, lock=False) # current left, right gripper state(2) data.
dual_gripper_action_array = Array('d', 2, lock=False) # current left, right gripper action(2) data.
gripper_ctrl = Gripper_Controller(left_hand_array, right_hand_array, dual_gripper_data_lock, dual_gripper_state_array, dual_gripper_action_array)
+ elif args.hand == "inspire1":
+ print("Inspire1_Controller comming soon.")
+ pass
+ else:
+ pass
if args.record:
recorder = EpisodeWriter(task_dir = args.task_dir, frequency = args.frequency, rerun_log = True)