feat: 加载STL模型
This commit is contained in:
parent
8ca84bbbad
commit
11f369452c
124
package.json
124
package.json
@ -1,61 +1,63 @@
|
|||||||
{
|
{
|
||||||
"name": "CMVR-IOT-UI",
|
"name": "CMVR-IOT-UI",
|
||||||
"version": "3.8.8",
|
"version": "3.8.8",
|
||||||
"description": "CMVR-IOT平台管理系统前端UI框架",
|
"description": "CMVR-IOT平台管理系统前端UI框架",
|
||||||
"author": "CMVR",
|
"author": "CMVR",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build:dev": "vite build --mode development",
|
"build:dev": "vite build --mode development",
|
||||||
"build:prod": "vite build --mode production",
|
"build:prod": "vite build --mode production",
|
||||||
"build:test": "vite build --mode test",
|
"build:test": "vite build --mode test",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "2.3.1",
|
"@element-plus/icons-vue": "2.3.1",
|
||||||
"@logicflow/core": "^2.0.13",
|
"@logicflow/core": "^2.0.13",
|
||||||
"@logicflow/extension": "^2.0.18",
|
"@logicflow/extension": "^2.0.18",
|
||||||
"@vueup/vue-quill": "1.2.0",
|
"@vueup/vue-quill": "1.2.0",
|
||||||
"@vueuse/core": "10.11.0",
|
"@vueuse/core": "10.11.0",
|
||||||
"ace-builds": "^1.43.0",
|
"ace-builds": "^1.43.0",
|
||||||
"axios": "0.28.1",
|
"axios": "0.28.1",
|
||||||
"clipboard": "2.0.11",
|
"clipboard": "2.0.11",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"echarts": "5.5.1",
|
"echarts": "5.5.1",
|
||||||
"element-plus": "2.9.4",
|
"element-plus": "2.9.4",
|
||||||
"file-saver": "2.0.5",
|
"file-saver": "2.0.5",
|
||||||
"fuse.js": "6.6.2",
|
"fuse.js": "6.6.2",
|
||||||
"js-beautify": "1.14.11",
|
"js-beautify": "1.14.11",
|
||||||
"js-cookie": "3.0.5",
|
"js-cookie": "3.0.5",
|
||||||
"jsencrypt": "3.3.2",
|
"jsencrypt": "3.3.2",
|
||||||
"json-editor-vue": "^0.18.1",
|
"json-editor-vue": "^0.18.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"mitt": "^3.0.1",
|
"mitt": "^3.0.1",
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
"pako": "^2.1.0",
|
"pako": "^2.1.0",
|
||||||
"pinia": "2.1.7",
|
"pinia": "2.1.7",
|
||||||
"pnpm": "^10.23.0",
|
"pnpm": "^10.23.0",
|
||||||
"socket.io-client": "^4.8.1",
|
"socket.io-client": "^4.8.1",
|
||||||
"sockjs-client": "^1.6.1",
|
"sockjs-client": "^1.6.1",
|
||||||
"splitpanes": "3.1.5",
|
"splitpanes": "3.1.5",
|
||||||
"uuid": "^11.1.0",
|
"three": "^0.181.2",
|
||||||
"vue": "3.4.31",
|
"urdf-loader": "^0.12.6",
|
||||||
"vue-cropper": "1.1.1",
|
"uuid": "^11.1.0",
|
||||||
"vue-router": "4.4.0",
|
"vue": "3.4.31",
|
||||||
"vue3-ace-editor": "^2.2.4",
|
"vue-cropper": "1.1.1",
|
||||||
"vue3-json-viewer": "2.3.0",
|
"vue-router": "4.4.0",
|
||||||
"vuedraggable": "4.1.0",
|
"vue3-ace-editor": "^2.2.4",
|
||||||
"xgplayer": "^3.0.22"
|
"vue3-json-viewer": "2.3.0",
|
||||||
},
|
"vuedraggable": "4.1.0",
|
||||||
"devDependencies": {
|
"xgplayer": "^3.0.22"
|
||||||
"@vitejs/plugin-vue": "5.0.5",
|
},
|
||||||
"file-loader": "^6.2.0",
|
"devDependencies": {
|
||||||
"sass": "1.77.5",
|
"@vitejs/plugin-vue": "5.0.5",
|
||||||
"unplugin-auto-import": "0.17.6",
|
"file-loader": "^6.2.0",
|
||||||
"unplugin-vue-setup-extend-plus": "1.0.1",
|
"sass": "1.77.5",
|
||||||
"vite": "5.3.2",
|
"unplugin-auto-import": "0.17.6",
|
||||||
"vite-plugin-compression": "0.5.1",
|
"unplugin-vue-setup-extend-plus": "1.0.1",
|
||||||
"vite-plugin-svg-icons": "2.0.1"
|
"vite": "5.3.2",
|
||||||
}
|
"vite-plugin-compression": "0.5.1",
|
||||||
}
|
"vite-plugin-svg-icons": "2.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
660
public/models/dual_arm.urdf
Normal file
660
public/models/dual_arm.urdf
Normal file
@ -0,0 +1,660 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<robot name="dual_arm">
|
||||||
|
<mujoco>
|
||||||
|
<compiler
|
||||||
|
meshdir="meshes"
|
||||||
|
balanceinertia="true"
|
||||||
|
discardvisual="false" />
|
||||||
|
</mujoco>
|
||||||
|
|
||||||
|
|
||||||
|
<link name="base_link">
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0.6" rpy="0 0 0"/>
|
||||||
|
<geometry>
|
||||||
|
<cylinder radius="0.05" length="1.2"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="gray">
|
||||||
|
<color rgba="0.5 0.5 0.5 1.0"/>
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0.6" rpy="0 0 0"/>
|
||||||
|
<geometry>
|
||||||
|
<cylinder radius="0.05" length="1.2"/>
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
|
||||||
|
<inertial>
|
||||||
|
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0"/>
|
||||||
|
<mass value="25.4469"/>
|
||||||
|
|
||||||
|
<inertia
|
||||||
|
ixx="3.06953"
|
||||||
|
ixy="0.0"
|
||||||
|
ixz="0.0"
|
||||||
|
iyy="3.06953"
|
||||||
|
iyz="0.0"
|
||||||
|
izz="0.03181"/>
|
||||||
|
</inertial>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="base_fixed" type="fixed">
|
||||||
|
<origin rpy="0 0 0" xyz="0 0 1.2"/>
|
||||||
|
<parent link="base_link"/>
|
||||||
|
<child link="PELVIS_S"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="PELVIS_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="3.78529087037144E-05 3.81781425684836E-07 0.0386396273530852" rpy="0 0 0" />
|
||||||
|
<mass value="2.10624590271277" />
|
||||||
|
<inertia
|
||||||
|
ixx="0.00165706865324979"
|
||||||
|
ixy="3.13663044821662E-09"
|
||||||
|
ixz="6.84209533216046E-07"
|
||||||
|
iyy="0.00136736758630241"
|
||||||
|
iyz="-1.01014607878816E-10"
|
||||||
|
izz="0.00168295663089359" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/PELVIS_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.698039215686274 0.698039215686274 0.698039215686274 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/PELVIS_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<link name="L_SHOULDER_P_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.00982258725282134 0.0704593083751867 1.15261874861217E-06" rpy="0 0 0" />
|
||||||
|
<mass value="0.880737519698403" />
|
||||||
|
<inertia
|
||||||
|
ixx="0.000583190308378148"
|
||||||
|
ixy="-1.53153074560473E-05"
|
||||||
|
ixz="6.58466471754072E-09"
|
||||||
|
iyy="0.000445532440067177"
|
||||||
|
iyz="6.37001404038516E-09"
|
||||||
|
izz="0.000465648071069952" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_SHOULDER_P_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.898039215686275 0.917647058823529 0.929411764705882 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_SHOULDER_P_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="L_SHOULDER_P" type="revolute">
|
||||||
|
<origin xyz="0 0.0945 0.042" rpy="0 0 0" />
|
||||||
|
<parent link="PELVIS_S" />
|
||||||
|
<child link="L_SHOULDER_P_S" />
|
||||||
|
<axis xyz="0 1 0" />
|
||||||
|
<limit lower="-1.57" upper="1.57" effort="120" velocity="3.351" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="L_SHOULDER_R_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.0346025282975857 0.091739327988169 -1.67085072999562E-08" rpy="0 0 0" />
|
||||||
|
<mass value="0.594788424442483" />
|
||||||
|
<inertia
|
||||||
|
ixx="0.000380970396712656"
|
||||||
|
ixy="4.80751844573946E-05"
|
||||||
|
ixz="-1.34913746586865E-11"
|
||||||
|
iyy="0.000320962178597474"
|
||||||
|
iyz="-1.00039763442409E-09"
|
||||||
|
izz="0.000414771047901155" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_SHOULDER_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.890196078431372 0.890196078431372 0.913725490196078 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_SHOULDER_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="L_SHOULDER_R" type="revolute">
|
||||||
|
<origin xyz="0.035 0.0765 0" rpy="0 0 0" />
|
||||||
|
<parent link="L_SHOULDER_P_S" />
|
||||||
|
<child link="L_SHOULDER_R_S" />
|
||||||
|
<axis xyz="1 0 0" />
|
||||||
|
<limit lower="-2" upper="2" effort="120" velocity="3.351" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="L_SHOULDER_Y_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.00440976862014801 0.0863620459174068 9.50748668682166E-09"
|
||||||
|
rpy="0 0 0" />
|
||||||
|
<mass value="0.563406026626801" />
|
||||||
|
<inertia
|
||||||
|
ixx="0.000327003834287552"
|
||||||
|
ixy="-1.8057438966771E-05"
|
||||||
|
ixz="7.28778136267901E-10"
|
||||||
|
iyy="0.000213830709361531"
|
||||||
|
iyz="1.49273668517817E-10"
|
||||||
|
izz="0.000297341029639189" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_SHOULDER_Y_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.890196078431372 0.890196078431372 0.913725490196078 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_SHOULDER_Y_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="L_SHOULDER_Y" type="revolute">
|
||||||
|
<origin xyz="-0.035 0.1475 0" rpy="0 0 0" />
|
||||||
|
<parent link="L_SHOULDER_R_S" />
|
||||||
|
<child link="L_SHOULDER_Y_S" />
|
||||||
|
<axis xyz="0 1 0" />
|
||||||
|
<limit lower="-2.18" upper="0" effort="80" velocity="3.8758" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="L_ELBOW_R_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.0335624237303443 0.0603199964106564 2.99655911639718E-07" rpy="0 0 0" />
|
||||||
|
<mass value="0.393571904406493" />
|
||||||
|
<inertia
|
||||||
|
ixx="0.00017277119386253"
|
||||||
|
ixy="2.34549801867355E-05"
|
||||||
|
ixz="-1.90560556659271E-09"
|
||||||
|
iyy="0.000155340245267897"
|
||||||
|
iyz="8.82493073600007E-09"
|
||||||
|
izz="0.00018104232734159" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_ELBOW_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.890196078431372 0.890196078431372 0.913725490196078 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_ELBOW_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="L_ELBOW_R" type="revolute">
|
||||||
|
<origin xyz="0.034 0.1025 0" rpy="0 0 0" />
|
||||||
|
<parent link="L_SHOULDER_Y_S" />
|
||||||
|
<child link="L_ELBOW_R_S" />
|
||||||
|
<axis xyz="1 0 0" />
|
||||||
|
<limit lower="-2.05" upper="0" effort="50" velocity="4.71" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="L_WRIST_P_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-1.39659173115092E-10 0.0675972604744393 0.019200551565574" rpy="0 0 0" />
|
||||||
|
<mass value="0.442332465815496" />
|
||||||
|
<inertia
|
||||||
|
ixx="0.000476754055455895"
|
||||||
|
ixy="-4.61505824713347E-15"
|
||||||
|
ixz="6.03808112272229E-18"
|
||||||
|
iyy="0.000103466585850499"
|
||||||
|
iyz="-4.88426705501198E-05"
|
||||||
|
izz="0.000482956345754213" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_WRIST_P_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.698039215686274 0.698039215686274 0.698039215686274 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_WRIST_P_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="L_WRIST_P" type="revolute">
|
||||||
|
<origin xyz="-0.034 0.0965 0" rpy="0 0 0" />
|
||||||
|
<parent link="L_ELBOW_R_S" />
|
||||||
|
<child link="L_WRIST_P_S" />
|
||||||
|
<axis xyz="0 1 0" />
|
||||||
|
<limit lower="0" upper="3.14" effort="50" velocity="4.71" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="L_WRIST_Y_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.00464135887331864 -5.06426789392833E-10 -0.0341253783666609" rpy="0 0 0" />
|
||||||
|
<mass value="0.23573847772002" />
|
||||||
|
<inertia
|
||||||
|
ixx="5.10686940455785E-05"
|
||||||
|
ixy="7.45706654358429E-16"
|
||||||
|
ixz="6.2619568923368E-06"
|
||||||
|
iyy="6.00636019624519E-05"
|
||||||
|
iyz="1.27989654155383E-16"
|
||||||
|
izz="5.32182903609189E-05" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_WRIST_Y_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.647058823529412 0.619607843137255 0.588235294117647 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_WRIST_Y_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="L_WRIST_Y" type="revolute">
|
||||||
|
<origin xyz="0 0.1525 0.039" rpy="0 0 0" />
|
||||||
|
<parent link="L_WRIST_P_S" />
|
||||||
|
<child link="L_WRIST_Y_S" />
|
||||||
|
<axis xyz="0 0 1" />
|
||||||
|
<limit lower="-0.78" upper="0.78" effort="50" velocity="0.79" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="L_WRIST_R_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.0161477357620243 0.0955046558857351 -0.00499392489444117" rpy="0 0 0" />
|
||||||
|
<mass value="0.504894112043562" />
|
||||||
|
<inertia
|
||||||
|
ixx="0.000186833711781125"
|
||||||
|
ixy="-3.99488705622731E-06"
|
||||||
|
ixz="-1.51920720398336E-06"
|
||||||
|
iyy="0.000179960980467837"
|
||||||
|
iyz="3.6992669535716E-06"
|
||||||
|
izz="0.000280756101568308" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_WRIST_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.890196078431372 0.890196078431372 0.913725490196078 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_WRIST_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="L_WRIST_R" type="revolute">
|
||||||
|
<origin xyz="0.0258 0 -0.039" rpy="0 0 0" />
|
||||||
|
<parent link="L_WRIST_Y_S" />
|
||||||
|
<child link="L_WRIST_R_S" />
|
||||||
|
<axis xyz="1 0 0" />
|
||||||
|
<limit lower="-1.57" upper="0.26" effort="50" velocity="4.71" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="R_SHOULDER_P_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.00982258725282141 -0.0704593093873431 -1.15069920925137E-06" rpy="0 0 0" />
|
||||||
|
<mass value="0.880737519698404" />
|
||||||
|
<inertia
|
||||||
|
ixx="0.000583190308378149"
|
||||||
|
ixy="1.53153074560471E-05"
|
||||||
|
ixz="-6.58466471736542E-09"
|
||||||
|
iyy="0.000445532440067178"
|
||||||
|
iyz="6.37001403998779E-09"
|
||||||
|
izz="0.000465648071069953" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_SHOULDER_P_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.890196078431372 0.890196078431372 0.913725490196078 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_SHOULDER_P_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="R_SHOULDER_P" type="revolute">
|
||||||
|
<origin xyz="0 -0.0945 0.042" rpy="0 0 0" />
|
||||||
|
<parent link="PELVIS_S" />
|
||||||
|
<child link="R_SHOULDER_P_S" />
|
||||||
|
<axis xyz="0 -1 0" />
|
||||||
|
<limit lower="-3.14" upper="3.14" effort="120" velocity="3.351" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="R_SHOULDER_R_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.0346025282975784 -0.09173932900033 1.86280643132974E-08" rpy="0 0 0" />
|
||||||
|
<mass value="0.59478842444248" />
|
||||||
|
<inertia
|
||||||
|
ixx="0.000380970396712653"
|
||||||
|
ixy="-4.80751844573946E-05"
|
||||||
|
ixz="1.34913746041655E-11"
|
||||||
|
iyy="0.000320962178597472"
|
||||||
|
iyz="-1.00039763417375E-09"
|
||||||
|
izz="0.000414771047901152" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_SHOULDER_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.890196078431372 0.890196078431372 0.913725490196078 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_SHOULDER_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="R_SHOULDER_R" type="revolute">
|
||||||
|
<origin xyz="0.035 -0.0765 0" rpy="0 0 0" />
|
||||||
|
<parent link="R_SHOULDER_P_S" />
|
||||||
|
<child link="R_SHOULDER_R_S" />
|
||||||
|
<axis xyz="1 0 0" />
|
||||||
|
<limit lower="-0.78" upper="1.57" effort="120" velocity="3.351" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="R_SHOULDER_Y_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.00440976862014946 -0.0863620469295699 -7.58791862676134E-09" rpy="0 0 0" />
|
||||||
|
<mass value="0.563406026626801" />
|
||||||
|
<inertia
|
||||||
|
ixx="0.000327003834287551"
|
||||||
|
ixy="1.80574389667711E-05"
|
||||||
|
ixz="-7.28778136077729E-10"
|
||||||
|
iyy="0.000213830709361532"
|
||||||
|
iyz="1.49273668428957E-10"
|
||||||
|
izz="0.000297341029639189" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_SHOULDER_Y_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material
|
||||||
|
name="">
|
||||||
|
<color rgba="0.890196078431372 0.890196078431372 0.913725490196078 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_SHOULDER_Y_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="R_SHOULDER_Y" type="revolute">
|
||||||
|
<origin xyz="-0.035 -0.1475 0" rpy="0 0 0" />
|
||||||
|
<parent link="R_SHOULDER_R_S" />
|
||||||
|
<child link="R_SHOULDER_Y_S" />
|
||||||
|
<axis xyz="0 -1 0" />
|
||||||
|
<limit lower="-3.14" upper="3.14" effort="80" velocity="3.8758" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="R_ELBOW_R_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.0335624237303424 -0.0603199974228191 -2.97736340082455E-07" rpy="0 0 0" />
|
||||||
|
<mass value="0.393571904406492" />
|
||||||
|
<inertia
|
||||||
|
ixx="0.000172771193862529"
|
||||||
|
ixy="-2.34549801867353E-05"
|
||||||
|
ixz="1.90560556668771E-09"
|
||||||
|
iyy="0.000155340245267897"
|
||||||
|
iyz="8.82493073602971E-09"
|
||||||
|
izz="0.00018104232734159" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_ELBOW_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.890196078431372 0.890196078431372 0.913725490196078 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_ELBOW_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="R_ELBOW_R" type="revolute">
|
||||||
|
<origin xyz="0.034 -0.1025 0" rpy="0 0 0" />
|
||||||
|
<parent link="R_SHOULDER_Y_S" />
|
||||||
|
<child link="R_ELBOW_R_S" />
|
||||||
|
<axis xyz="1 0 0" />
|
||||||
|
<limit lower="0" upper="2.05" effort="80" velocity="3.8758" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="R_WRIST_P_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-1.39656577968772E-10 -0.0675972614865965 0.0192005515655728" rpy="0 0 0" />
|
||||||
|
<mass value="0.442332465815497" />
|
||||||
|
<inertia
|
||||||
|
ixx="0.000476754055455896"
|
||||||
|
ixy="-4.61462558956188E-15"
|
||||||
|
ixz="-5.91762926004267E-18"
|
||||||
|
iyy="0.0001034665858505"
|
||||||
|
iyz="4.88426705501212E-05"
|
||||||
|
izz="0.000482956345754214" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_WRIST_P_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.647058823529412 0.619607843137255 0.588235294117647 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_WRIST_P_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="R_WRIST_P" type="revolute">
|
||||||
|
<origin xyz="-0.034 -0.0965 0" rpy="0 0 0" />
|
||||||
|
<parent link="R_ELBOW_R_S" />
|
||||||
|
<child link="R_WRIST_P_S" />
|
||||||
|
<axis xyz="0 -1 0" />
|
||||||
|
<limit lower="-3.14" upper="3.14" effort="50" velocity="4.71" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="R_WRIST_Y_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.00464135887330083 -5.06426456325926E-10 -0.0341253783666614" rpy="0 0 0" />
|
||||||
|
<mass value="0.235738477720019" />
|
||||||
|
<inertia
|
||||||
|
ixx="5.1068694045578E-05"
|
||||||
|
ixy="7.45771487459288E-16"
|
||||||
|
ixz="6.26195689233664E-06"
|
||||||
|
iyy="6.00636019624515E-05"
|
||||||
|
iyz="1.27828046342987E-16"
|
||||||
|
izz="5.32182903609188E-05" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_WRIST_Y_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.647058823529412 0.619607843137255 0.588235294117647 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_WRIST_Y_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="R_WRIST_Y" type="revolute">
|
||||||
|
<origin xyz="0 -0.1525 0.039" rpy="0 0 0" />
|
||||||
|
<parent link="R_WRIST_P_S" />
|
||||||
|
<child link="R_WRIST_Y_S" />
|
||||||
|
<axis xyz="0 0 1" />
|
||||||
|
<limit lower="-0.78" upper="0.78" effort="50" velocity="0.79" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="R_WRIST_R_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.0201642233698132 -0.11074968386657 -0.00598955339232021" rpy="0 0 0" />
|
||||||
|
<mass value="0.504366058218534" />
|
||||||
|
<inertia
|
||||||
|
ixx="0.000185559065855467"
|
||||||
|
ixy="5.75889766751509E-06"
|
||||||
|
ixz="2.40683898454438E-06"
|
||||||
|
iyy="0.000131246007872084"
|
||||||
|
iyz="1.60533277040148E-06"
|
||||||
|
izz="0.000271800951396149" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_WRIST_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material
|
||||||
|
name="">
|
||||||
|
<color rgba="0.890196078431372 0.890196078431372 0.913725490196078 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_WRIST_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="R_WRIST_R" type="revolute">
|
||||||
|
<origin xyz="0.03 0 -0.039" rpy="0 0 0" />
|
||||||
|
<parent link="R_WRIST_Y_S" />
|
||||||
|
<child link="R_WRIST_R_S" />
|
||||||
|
<axis xyz="1 0 0" />
|
||||||
|
<limit lower="-0.26" upper="1.57" effort="50" velocity="4.71" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="R_FINGER_TIP">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0"/>
|
||||||
|
<mass value="0"/>
|
||||||
|
<inertia ixx="1e-6" ixy="0" ixz="0" iyy="1e-6" iyz="0" izz="1e-6"/>
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0"/>
|
||||||
|
<geometry>
|
||||||
|
<sphere radius="0.004"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0 1 1 1"/> <!-- 绿色 -->
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0"/>
|
||||||
|
<geometry>
|
||||||
|
<sphere radius="0.005"/>
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="R_FINGER_TIP_FIXED" type="fixed">
|
||||||
|
<origin xyz="0.00684256 -0.284077 0.00801525" rpy="0 0 0"/>
|
||||||
|
<parent link="R_WRIST_R_S"/>
|
||||||
|
<child link="R_FINGER_TIP"/>
|
||||||
|
<axis xyz="0 0 1"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="R_CAM">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0"/>
|
||||||
|
<mass value="0"/>
|
||||||
|
<inertia ixx="1e-6" ixy="0" ixz="0" iyy="1e-6" iyz="0" izz="1e-6"/>
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0"/>
|
||||||
|
<geometry>
|
||||||
|
<sphere radius="0.004"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0 1 0 1"/> <!-- 绿色 -->
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0"/>
|
||||||
|
<geometry>
|
||||||
|
<sphere radius="0.005"/>
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="R_CAM_FIXED" type="fixed">
|
||||||
|
<origin xyz="-0.01212 -0.17655 0.07506" rpy="-1.5707963267 0 3.1415926535"/>
|
||||||
|
<parent link="R_WRIST_R_S"/>
|
||||||
|
<child link="R_CAM"/>
|
||||||
|
<axis xyz="0 0 1"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
</robot>
|
||||||
281
public/models/left_arm.urdf
Normal file
281
public/models/left_arm.urdf
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<robot name="left_arm">
|
||||||
|
<mujoco>
|
||||||
|
<compiler
|
||||||
|
meshdir="meshes"
|
||||||
|
balanceinertia="true"
|
||||||
|
discardvisual="false" />
|
||||||
|
</mujoco>
|
||||||
|
<link name="base_link">
|
||||||
|
<visual>
|
||||||
|
<geometry>
|
||||||
|
<cylinder radius="0.05" length="1.2"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="gray">
|
||||||
|
<color rgba="0.5 0.5 0.5 1.0"/>
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
|
||||||
|
<collision>
|
||||||
|
<geometry>
|
||||||
|
<cylinder radius="0.05" length="1.2"/>
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
|
||||||
|
<inertial>
|
||||||
|
<mass value="20.0"/>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0"/>
|
||||||
|
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
|
||||||
|
</inertial>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="base_fixed" type="fixed">
|
||||||
|
<origin rpy="0 0 0.0" xyz="0 0 0.6"/>
|
||||||
|
<parent link="base_link"/>
|
||||||
|
<child link="PELVIS_S"/>
|
||||||
|
<axis xyz="0 0 0"/>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="PELVIS_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="3.78529087037144E-05 3.81781425684836E-07 0.0386396273530852" rpy="0 0 0" />
|
||||||
|
<mass value="2.10624590271277" />
|
||||||
|
<inertia ixx="0.00165706865324979" ixy="3.13663044821662E-09" ixz="6.84209533216046E-07" iyy="0.00136736758630241" iyz="-1.01014607878816E-10" izz="0.00168295663089359" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/PELVIS_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.698039215686274 0.698039215686274 0.698039215686274 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/PELVIS_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="L_SHOULDER_P" type="revolute">
|
||||||
|
<origin xyz="0 0.0945 0.042" rpy="0 0 0" />
|
||||||
|
<parent link="PELVIS_S" />
|
||||||
|
<child link="L_SHOULDER_P_S" />
|
||||||
|
<axis xyz="0 1 0" />
|
||||||
|
<limit lower="-3.14" upper="3.14" effort="100" velocity="3.351" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="L_SHOULDER_P_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.00982258725282134 0.0704593083751867 1.15261874861217E-06" rpy="0 0 0" />
|
||||||
|
<mass value="0.880737519698403" />
|
||||||
|
<inertia ixx="0.000583190308378148" ixy="-1.53153074560473E-05" ixz="6.58466471754072E-09" iyy="0.000445532440067177" iyz="6.37001404038516E-09" izz="0.000465648071069952" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_SHOULDER_P_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material
|
||||||
|
name="">
|
||||||
|
<color rgba="0.898039215686275 0.917647058823529 0.929411764705882 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_SHOULDER_P_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="L_SHOULDER_R" type="revolute">
|
||||||
|
<origin xyz="0.035 0.0765 0" rpy="0 0 0" />
|
||||||
|
<parent link="L_SHOULDER_P_S" />
|
||||||
|
<child link="L_SHOULDER_R_S" />
|
||||||
|
<axis xyz="1 0 0" />
|
||||||
|
<limit lower="-3.14" upper="3.14" effort="100" velocity="3.351" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="L_SHOULDER_R_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.0346025282975857 0.091739327988169 -1.67085072999562E-08" rpy="0 0 0" />
|
||||||
|
<mass value="0.594788424442483" />
|
||||||
|
<inertia ixx="0.000380970396712656" ixy="4.80751844573946E-05" ixz="-1.34913746586865E-11" iyy="0.000320962178597474" iyz="-1.00039763442409E-09" izz="0.000414771047901155" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_SHOULDER_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.890196078431372 0.890196078431372 0.913725490196078 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_SHOULDER_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="L_SHOULDER_Y" type="revolute">
|
||||||
|
<origin xyz="-0.035 0.1475 0" rpy="0 0 0" />
|
||||||
|
<parent link="L_SHOULDER_R_S" />
|
||||||
|
<child link="L_SHOULDER_Y_S" />
|
||||||
|
<axis xyz="0 1 0" />
|
||||||
|
<limit lower="-3.14" upper="3.14" effort="49" velocity="3.8758" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="L_SHOULDER_Y_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.00440976862014801 0.0863620459174068 9.50748668682166E-09" rpy="0 0 0" />
|
||||||
|
<mass value="0.563406026626801" />
|
||||||
|
<inertia ixx="0.000327003834287552" ixy="-1.8057438966771E-05" ixz="7.28778136267901E-10" iyy="0.000213830709361531" iyz="1.49273668517817E-10" izz="0.000297341029639189" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_SHOULDER_Y_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.890196078431372 0.890196078431372 0.913725490196078 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_SHOULDER_Y_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="L_ELBOW_R" type="revolute">
|
||||||
|
<origin xyz="0.034 0.1025 0" rpy="0 0 0" />
|
||||||
|
<parent link="L_SHOULDER_Y_S" />
|
||||||
|
<child link="L_ELBOW_R_S" />
|
||||||
|
<axis xyz="1 0 0" />
|
||||||
|
<limit lower="-3.14" upper="3.14" effort="49" velocity="3.8758" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="L_ELBOW_R_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.0335624237303443 0.0603199964106564 2.99655911639718E-07" rpy="0 0 0" />
|
||||||
|
<mass value="0.393571904406493" />
|
||||||
|
<inertia ixx="0.00017277119386253" ixy="2.34549801867355E-05" ixz="-1.90560556659271E-09" iyy="0.000155340245267897" iyz="8.82493073600007E-09" izz="0.00018104232734159" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_ELBOW_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.890196078431372 0.890196078431372 0.913725490196078 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_ELBOW_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="L_WRIST_P" type="revolute">
|
||||||
|
<origin xyz="-0.034 0.0965 0" rpy="0 0 0" />
|
||||||
|
<parent link="L_ELBOW_R_S" />
|
||||||
|
<child link="L_WRIST_P_S" />
|
||||||
|
<axis xyz="0 1 0" />
|
||||||
|
<limit lower="-3.14" upper="3.14" effort="26" velocity="4.19" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="L_WRIST_P_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-1.39659173115092E-10 0.0675972604744393 0.019200551565574" rpy="0 0 0" />
|
||||||
|
<mass value="0.442332465815496" />
|
||||||
|
<inertia ixx="0.000476754055455895" ixy="-4.61505824713347E-15" ixz="6.03808112272229E-18" iyy="0.000103466585850499" iyz="-4.88426705501198E-05" izz="0.000482956345754213" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_WRIST_P_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.698039215686274 0.698039215686274 0.698039215686274 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_WRIST_P_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="L_WRIST_Y" type="revolute">
|
||||||
|
<origin xyz="0 0.1525 0.039" rpy="0 0 0" />
|
||||||
|
<parent link="L_WRIST_P_S" />
|
||||||
|
<child link="L_WRIST_Y_S" />
|
||||||
|
<axis xyz="0 0 1" />
|
||||||
|
<limit lower="-3.14" upper="3.14" effort="26" velocity="4.71" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="L_WRIST_Y_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.00464135887331864 -5.06426789392833E-10 -0.0341253783666609" rpy="0 0 0" />
|
||||||
|
<mass value="0.23573847772002" />
|
||||||
|
<inertia ixx="5.10686940455785E-05" ixy="7.45706654358429E-16" ixz="6.2619568923368E-06" iyy="6.00636019624519E-05" iyz="1.27989654155383E-16" izz="5.32182903609189E-05" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_WRIST_Y_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.647058823529412 0.619607843137255 0.588235294117647 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_WRIST_Y_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="L_WRIST_R" type="revolute">
|
||||||
|
<origin xyz="0.0258 0 -0.039" rpy="0 0 0" />
|
||||||
|
<parent link="L_WRIST_Y_S" />
|
||||||
|
<child link="L_WRIST_R_S" />
|
||||||
|
<axis xyz="1 0 0" />
|
||||||
|
<limit lower="-3.14" upper="3.14" effort="26" velocity="4.71" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="L_WRIST_R_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.0161477357620243 0.0955046558857351 -0.00499392489444117" rpy="0 0 0" />
|
||||||
|
<mass value="0.504894112043562" />
|
||||||
|
<inertia ixx="0.000186833711781125" ixy="-3.99488705622731E-06" ixz="-1.51920720398336E-06" iyy="0.000179960980467837" iyz="3.6992669535716E-06" izz="0.000280756101568308" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_WRIST_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.890196078431372 0.890196078431372 0.913725490196078 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/L_WRIST_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
|
||||||
|
</robot>
|
||||||
BIN
public/models/meshes/L_ELBOW_R_S.STL
Normal file
BIN
public/models/meshes/L_ELBOW_R_S.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/L_SHOULDER_P_S.STL
Normal file
BIN
public/models/meshes/L_SHOULDER_P_S.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/L_SHOULDER_R_S.STL
Normal file
BIN
public/models/meshes/L_SHOULDER_R_S.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/L_SHOULDER_Y_S.STL
Normal file
BIN
public/models/meshes/L_SHOULDER_Y_S.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/L_WRIST_P_S.STL
Normal file
BIN
public/models/meshes/L_WRIST_P_S.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/L_WRIST_R_S.STL
Normal file
BIN
public/models/meshes/L_WRIST_R_S.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/L_WRIST_Y_S.STL
Normal file
BIN
public/models/meshes/L_WRIST_Y_S.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/NECK_P_S.STL
Normal file
BIN
public/models/meshes/NECK_P_S.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/NECK_R_S.STL
Normal file
BIN
public/models/meshes/NECK_R_S.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/NECK_Y_S.STL
Normal file
BIN
public/models/meshes/NECK_Y_S.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/PELVIS_S.STL
Normal file
BIN
public/models/meshes/PELVIS_S.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/R_ELBOW_R_S.STL
Normal file
BIN
public/models/meshes/R_ELBOW_R_S.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/R_SHOULDER_P_S.STL
Normal file
BIN
public/models/meshes/R_SHOULDER_P_S.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/R_SHOULDER_R_S.STL
Normal file
BIN
public/models/meshes/R_SHOULDER_R_S.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/R_SHOULDER_Y_S.STL
Normal file
BIN
public/models/meshes/R_SHOULDER_Y_S.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/R_WRIST_P_S.STL
Normal file
BIN
public/models/meshes/R_WRIST_P_S.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/R_WRIST_R_S.STL
Normal file
BIN
public/models/meshes/R_WRIST_R_S.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/R_WRIST_Y_S.STL
Normal file
BIN
public/models/meshes/R_WRIST_Y_S.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/base_link.STL
Normal file
BIN
public/models/meshes/base_link.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/index_force_sensor_1.STL
Normal file
BIN
public/models/meshes/index_force_sensor_1.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/index_force_sensor_2.STL
Normal file
BIN
public/models/meshes/index_force_sensor_2.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/index_force_sensor_3.STL
Normal file
BIN
public/models/meshes/index_force_sensor_3.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/little_force_sensor_1.STL
Normal file
BIN
public/models/meshes/little_force_sensor_1.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/little_force_sensor_2.STL
Normal file
BIN
public/models/meshes/little_force_sensor_2.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/little_force_sensor_3.STL
Normal file
BIN
public/models/meshes/little_force_sensor_3.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/middle_force_sensor_1.STL
Normal file
BIN
public/models/meshes/middle_force_sensor_1.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/middle_force_sensor_2.STL
Normal file
BIN
public/models/meshes/middle_force_sensor_2.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/middle_force_sensor_3.STL
Normal file
BIN
public/models/meshes/middle_force_sensor_3.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/palm_force_sensor.STL
Normal file
BIN
public/models/meshes/palm_force_sensor.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/right_index_1.STL
Normal file
BIN
public/models/meshes/right_index_1.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/right_index_2.STL
Normal file
BIN
public/models/meshes/right_index_2.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/right_little_1.STL
Normal file
BIN
public/models/meshes/right_little_1.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/right_little_2.STL
Normal file
BIN
public/models/meshes/right_little_2.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/right_middle_1.STL
Normal file
BIN
public/models/meshes/right_middle_1.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/right_middle_2.STL
Normal file
BIN
public/models/meshes/right_middle_2.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/right_ring_1.STL
Normal file
BIN
public/models/meshes/right_ring_1.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/right_ring_2.STL
Normal file
BIN
public/models/meshes/right_ring_2.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/right_thumb_1.STL
Normal file
BIN
public/models/meshes/right_thumb_1.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/right_thumb_2.STL
Normal file
BIN
public/models/meshes/right_thumb_2.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/right_thumb_3.STL
Normal file
BIN
public/models/meshes/right_thumb_3.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/right_thumb_4.STL
Normal file
BIN
public/models/meshes/right_thumb_4.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/ring_force_sensor_1.STL
Normal file
BIN
public/models/meshes/ring_force_sensor_1.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/ring_force_sensor_2.STL
Normal file
BIN
public/models/meshes/ring_force_sensor_2.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/ring_force_sensor_3.STL
Normal file
BIN
public/models/meshes/ring_force_sensor_3.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/thumb_force_sensor_1.STL
Normal file
BIN
public/models/meshes/thumb_force_sensor_1.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/thumb_force_sensor_2.STL
Normal file
BIN
public/models/meshes/thumb_force_sensor_2.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/thumb_force_sensor_3.STL
Normal file
BIN
public/models/meshes/thumb_force_sensor_3.STL
Normal file
Binary file not shown.
BIN
public/models/meshes/thumb_force_sensor_4.STL
Normal file
BIN
public/models/meshes/thumb_force_sensor_4.STL
Normal file
Binary file not shown.
322
public/models/right_arm.urdf
Normal file
322
public/models/right_arm.urdf
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<robot name="right_arm">
|
||||||
|
<mujoco>
|
||||||
|
<compiler
|
||||||
|
meshdir="meshes"
|
||||||
|
balanceinertia="true"
|
||||||
|
discardvisual="false" />
|
||||||
|
</mujoco>
|
||||||
|
<link name="PELVIS_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="3.78529e-05 3.81781e-07 0.0386396" rpy="0 0 0"/>
|
||||||
|
<mass value="2.10624590271277"/>
|
||||||
|
<inertia
|
||||||
|
ixx="0.00165706865324979" ixy="3.13663e-09" ixz="6.84210e-07"
|
||||||
|
iyy="0.00136736758630241" iyz="-1.01015e-10" izz="0.00168295663089359"/>
|
||||||
|
</inertial>
|
||||||
|
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0"/>
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/PELVIS_S.STL"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="light_gray">
|
||||||
|
<color rgba="0.698 0.698 0.698 1"/>
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0"/>
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/PELVIS_S.STL"/>
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<link name="R_SHOULDER_P_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.00982258725282141 -0.0704593093873431 -1.15069920925137E-06" rpy="0 0 0" />
|
||||||
|
<mass value="0.880737519698404" />
|
||||||
|
<inertia
|
||||||
|
ixx="0.000583190308378149"
|
||||||
|
ixy="1.53153074560471E-05"
|
||||||
|
ixz="-6.58466471736542E-09"
|
||||||
|
iyy="0.000445532440067178"
|
||||||
|
iyz="6.37001403998779E-09"
|
||||||
|
izz="0.000465648071069953" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_SHOULDER_P_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.890196078431372 0.890196078431372 0.913725490196078 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin
|
||||||
|
xyz="0 0 0"
|
||||||
|
rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_SHOULDER_P_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="R_SHOULDER_P" type="revolute">
|
||||||
|
<origin xyz="0 -0.0945 0.042" rpy="0 0 0" />
|
||||||
|
<parent link="PELVIS_S" />
|
||||||
|
<child link="R_SHOULDER_P_S" />
|
||||||
|
<axis xyz="0 -1 0" />
|
||||||
|
<limit lower="-1.57" upper="1.57" effort="120" velocity="3.351" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="R_SHOULDER_R_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.0346025282975784 -0.09173932900033 1.86280643132974E-08" rpy="0 0 0" />
|
||||||
|
<mass value="0.59478842444248" />
|
||||||
|
<inertia
|
||||||
|
ixx="0.000380970396712653" ixy="-4.80751844573946E-05" ixz="1.34913746041655E-11"
|
||||||
|
iyy="0.000320962178597472" iyz="-1.00039763417375E-09" izz="0.000414771047901152" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_SHOULDER_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.890196078431372 0.890196078431372 0.913725490196078 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_SHOULDER_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="R_SHOULDER_R" type="revolute">
|
||||||
|
<origin xyz="0.035 -0.0765 0" rpy="0 0 0" />
|
||||||
|
<parent link="R_SHOULDER_P_S" />
|
||||||
|
<child link="R_SHOULDER_R_S" />
|
||||||
|
<axis xyz="1 0 0" />
|
||||||
|
<limit lower="-2" upper="2" effort="120" velocity="3.351" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="R_SHOULDER_Y_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.00440976862014946 -0.0863620469295699 -7.58791862676134E-09" rpy="0 0 0" />
|
||||||
|
<mass value="0.563406026626801" />
|
||||||
|
<inertia
|
||||||
|
ixx="0.000327003834287551"
|
||||||
|
ixy="1.80574389667711E-05"
|
||||||
|
ixz="-7.28778136077729E-10"
|
||||||
|
iyy="0.000213830709361532"
|
||||||
|
iyz="1.49273668428957E-10"
|
||||||
|
izz="0.000297341029639189" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_SHOULDER_Y_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.890196078431372 0.890196078431372 0.913725490196078 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_SHOULDER_Y_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="R_SHOULDER_Y" type="revolute">
|
||||||
|
<origin xyz="-0.035 -0.1475 0" rpy="0 0 0" />
|
||||||
|
<parent link="R_SHOULDER_R_S" />
|
||||||
|
<child link="R_SHOULDER_Y_S" />
|
||||||
|
<axis xyz="0 -1 0" />
|
||||||
|
<limit lower="0" upper="3.14" effort="80" velocity="3.8758" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="R_ELBOW_R_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.0335624237303424 -0.0603199974228191 -2.97736340082455E-07" rpy="0 0 0" />
|
||||||
|
<mass value="0.393571904406492" />
|
||||||
|
<inertia
|
||||||
|
ixx="0.000172771193862529"
|
||||||
|
ixy="-2.34549801867353E-05"
|
||||||
|
ixz="1.90560556668771E-09"
|
||||||
|
iyy="0.000155340245267897"
|
||||||
|
iyz="8.82493073602971E-09"
|
||||||
|
izz="0.00018104232734159" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_ELBOW_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.890196078431372 0.890196078431372 0.913725490196078 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_ELBOW_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="R_ELBOW_R" type="revolute">
|
||||||
|
<origin xyz="0.034 -0.1025 0" rpy="0 0 0" />
|
||||||
|
<parent link="R_SHOULDER_Y_S" />
|
||||||
|
<child link="R_ELBOW_R_S" />
|
||||||
|
<axis xyz="1 0 0" />
|
||||||
|
<limit lower="0" upper="2.18" effort="80" velocity="3.8758" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="R_WRIST_P_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-1.39656577968772E-10 -0.0675972614865965 0.0192005515655728" rpy="0 0 0" />
|
||||||
|
<mass value="0.442332465815497" />
|
||||||
|
<inertia
|
||||||
|
ixx="0.000476754055455896"
|
||||||
|
ixy="-4.61462558956188E-15"
|
||||||
|
ixz="-5.91762926004267E-18"
|
||||||
|
iyy="0.0001034665858505"
|
||||||
|
iyz="4.88426705501212E-05"
|
||||||
|
izz="0.000482956345754214" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_WRIST_P_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.647058823529412 0.619607843137255 0.588235294117647 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_WRIST_P_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="R_WRIST_P" type="revolute">
|
||||||
|
<origin xyz="-0.034 -0.0965 0" rpy="0 0 0" />
|
||||||
|
<parent link="R_ELBOW_R_S" />
|
||||||
|
<child link="R_WRIST_P_S" />
|
||||||
|
<axis xyz="0 -1 0" />
|
||||||
|
<limit lower="-3.14" upper="0" effort="50" velocity="4.71" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="R_WRIST_Y_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.00464135887330083 -5.06426456325926E-10 -0.0341253783666614" rpy="0 0 0" />
|
||||||
|
<mass value="0.235738477720019" />
|
||||||
|
<inertia
|
||||||
|
ixx="5.1068694045578E-05"
|
||||||
|
ixy="7.45771487459288E-16"
|
||||||
|
ixz="6.26195689233664E-06"
|
||||||
|
iyy="6.00636019624515E-05"
|
||||||
|
iyz="1.27828046342987E-16"
|
||||||
|
izz="5.32182903609188E-05" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_WRIST_Y_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.647058823529412 0.619607843137255 0.588235294117647 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_WRIST_Y_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="R_WRIST_Y" type="revolute">
|
||||||
|
<origin xyz="0 -0.1525 0.039" rpy="0 0 0" />
|
||||||
|
<parent link="R_WRIST_P_S" />
|
||||||
|
<child link="R_WRIST_Y_S" />
|
||||||
|
<axis xyz="0 0 1" />
|
||||||
|
<limit lower="0" upper="0.78" effort="50" velocity="0.79" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="R_WRIST_R_S">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="-0.0201642233698132 -0.11074968386657 -0.00598955339232021" rpy="0 0 0" />
|
||||||
|
<mass value="0.204366058218534" />
|
||||||
|
<inertia
|
||||||
|
ixx="0.000185559065855467"
|
||||||
|
ixy="5.75889766751509E-06"
|
||||||
|
ixz="2.40683898454438E-06"
|
||||||
|
iyy="0.000131246007872084"
|
||||||
|
iyz="1.60533277040148E-06"
|
||||||
|
izz="0.000271800951396149" />
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_WRIST_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0.890196078431372 0.890196078431372 0.913725490196078 1" />
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||||
|
<geometry>
|
||||||
|
<mesh filename="meshes/R_WRIST_R_S.STL" />
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="R_WRIST_R" type="revolute">
|
||||||
|
<origin xyz="0.03 0 -0.039" rpy="0 0 0" />
|
||||||
|
<parent link="R_WRIST_Y_S" />
|
||||||
|
<child link="R_WRIST_R_S" />
|
||||||
|
<axis xyz="1 0 0" />
|
||||||
|
<limit lower="-0.26" upper="1.57" effort="50" velocity="4.71" />
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<link name="R_FINGER_TIP">
|
||||||
|
<inertial>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0"/>
|
||||||
|
<mass value="0"/>
|
||||||
|
<inertia ixx="1e-6" ixy="0" ixz="0" iyy="1e-6" iyz="0" izz="1e-6"/>
|
||||||
|
</inertial>
|
||||||
|
<visual>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0"/>
|
||||||
|
<geometry>
|
||||||
|
<sphere radius="0.002"/>
|
||||||
|
</geometry>
|
||||||
|
<material name="">
|
||||||
|
<color rgba="0 1 0 1"/> <!-- 绿色 -->
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
<collision>
|
||||||
|
<origin xyz="0 0 0" rpy="0 0 0"/>
|
||||||
|
<geometry>
|
||||||
|
<sphere radius="0.005"/>
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<joint name="R_FINGER_TIP_FIXED" type="fixed">
|
||||||
|
<origin xyz="-0.01212 -0.17655 0.07506" rpy="3.14159 0 -1.5708"/>
|
||||||
|
<parent link="R_WRIST_R_S"/>
|
||||||
|
<child link="R_FINGER_TIP"/>
|
||||||
|
</joint>
|
||||||
|
</robot>
|
||||||
@ -0,0 +1,133 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<div class="joint-control" v-for="joint in jointList" :key="joint.name">
|
||||||
|
<div class="joint-header">
|
||||||
|
<span class="joint-name">{{ joint.displayName }}</span>
|
||||||
|
<span class="joint-type">{{ joint.type.toUpperCase() }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="joint-info">
|
||||||
|
<span class="angle-display">{{ formatAngle(joint.value) }}</span>
|
||||||
|
<span class="limits">[{{ formatAngle(joint.min) }}, {{ formatAngle(joint.max) }}]</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="slider-container">
|
||||||
|
<el-slider size="small" v-model="joint.value" :min="joint.min" :max="joint.max" :step="joint.step" @input="(value) => updateJointAngle(joint.name, value)"/>
|
||||||
|
<div class="slider-labels">
|
||||||
|
<span>{{ formatAngle(joint.min) }}</span>
|
||||||
|
<span>{{ formatAngle(joint.max) }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
jointList: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const emits = defineEmits(['updateJointAngle'])
|
||||||
|
|
||||||
|
const updateJointAngle = (name, value) => {
|
||||||
|
emits('updateJointAngle', { name, value })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角度格式化
|
||||||
|
*/
|
||||||
|
const formatAngle = (radians) => {
|
||||||
|
const degrees = (radians * 180 / Math.PI).toFixed(1)
|
||||||
|
return `${degrees}°`
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.joint-control {
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 15px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
border: 1px solid #cfcfcf;
|
||||||
|
|
||||||
|
.joint-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
.joint-name {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.joint-type {
|
||||||
|
font-size: 11px;
|
||||||
|
background: rgba(52, 152, 219, 0.3);
|
||||||
|
color: #3498db;
|
||||||
|
padding: 3px 8px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.joint-info {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-size: 13px;
|
||||||
|
|
||||||
|
.angle-display {
|
||||||
|
color: #f1c40f;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.limits {
|
||||||
|
color: #95a5a6;
|
||||||
|
font-size: 11px;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider-container {
|
||||||
|
padding: 0 5px;
|
||||||
|
|
||||||
|
.joint-slider {
|
||||||
|
width: 100%;
|
||||||
|
height: 8px;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
background: #34495e;
|
||||||
|
border-radius: 4px;
|
||||||
|
outline: none;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&::-webkit-slider-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #ecf0f1;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 2px solid #3498db;
|
||||||
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider-labels {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 11px;
|
||||||
|
color: #7f8c8d;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,394 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 模板部分保持不变 -->
|
||||||
|
<div class="urdf-viewer-container">
|
||||||
|
|
||||||
|
<div ref="viewerContainer" class="urdf-viewer"></div>
|
||||||
|
|
||||||
|
<div v-if="isLoading" class="loading-overlay">
|
||||||
|
<div class="loading-spinner"></div>
|
||||||
|
<p>正在解析URDF并加载模型...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, onBeforeUnmount, watch, reactive, computed } from 'vue'
|
||||||
|
import * as THREE from 'three'
|
||||||
|
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
|
||||||
|
import URDFLoader from 'urdf-loader'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
basePath: { type: String, required: true },
|
||||||
|
urdfPath: { type: String, required: true },
|
||||||
|
modelColor: { type: String, default: '#cbcbcb' },
|
||||||
|
showJointLimits: { type: Boolean, default: true }
|
||||||
|
})
|
||||||
|
|
||||||
|
const emits = defineEmits(['computedChange'])
|
||||||
|
|
||||||
|
const viewerContainer = ref(null)
|
||||||
|
const isLoading = ref(false)
|
||||||
|
|
||||||
|
// Three.js 核心对象
|
||||||
|
let scene = null
|
||||||
|
let camera = null
|
||||||
|
let renderer = null
|
||||||
|
let controls = null
|
||||||
|
let robot = null
|
||||||
|
|
||||||
|
// 关节控制相关状态
|
||||||
|
const jointControls = reactive([])
|
||||||
|
const availableJoints = ref({})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从URDF XML中提取关节信息(使用浏览器原生DOMParser)
|
||||||
|
*/
|
||||||
|
const extractJointInfoFromURDF = (urdfXml) => {
|
||||||
|
try {
|
||||||
|
const joints = []
|
||||||
|
const parser = new DOMParser()
|
||||||
|
const xmlDoc = parser.parseFromString(urdfXml, 'text/xml')
|
||||||
|
|
||||||
|
// 检查解析错误
|
||||||
|
const parseError = xmlDoc.getElementsByTagName('parsererror')
|
||||||
|
if (parseError.length > 0) {
|
||||||
|
throw new Error('XML解析错误: ' + parseError[0].textContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取所有joint元素
|
||||||
|
const jointElements = xmlDoc.getElementsByTagName('joint')
|
||||||
|
|
||||||
|
for (let i = 0; i < jointElements.length; i++) {
|
||||||
|
const jointElement = jointElements[i]
|
||||||
|
const name = jointElement.getAttribute('name')
|
||||||
|
const type = jointElement.getAttribute('type')
|
||||||
|
|
||||||
|
// 只处理可动关节
|
||||||
|
if (type && ['revolute', 'continuous', 'prismatic'].includes(type)) {
|
||||||
|
const jointInfo = {
|
||||||
|
name: name,
|
||||||
|
displayName: name.replace(/_/g, ' '),
|
||||||
|
type: type,
|
||||||
|
value: 0,
|
||||||
|
step: 0.01
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取关节限制
|
||||||
|
const limitElements = jointElement.getElementsByTagName('limit')
|
||||||
|
if (limitElements.length > 0) {
|
||||||
|
const limit = limitElements[0]
|
||||||
|
const lower = limit.getAttribute('lower')
|
||||||
|
const upper = limit.getAttribute('upper')
|
||||||
|
const effort = limit.getAttribute('effort')
|
||||||
|
const velocity = limit.getAttribute('velocity')
|
||||||
|
|
||||||
|
// 处理旋转关节
|
||||||
|
if (type === 'revolute' || type === 'continuous') {
|
||||||
|
jointInfo.min = lower !== null ? parseFloat(lower) :
|
||||||
|
(type === 'revolute' ? -Math.PI : -Math.PI)
|
||||||
|
jointInfo.max = upper !== null ? parseFloat(upper) :
|
||||||
|
(type === 'revolute' ? Math.PI : Math.PI)
|
||||||
|
}
|
||||||
|
// 处理平移关节
|
||||||
|
else if (type === 'prismatic') {
|
||||||
|
jointInfo.min = lower !== null ? parseFloat(lower) : -1.0
|
||||||
|
jointInfo.max = upper !== null ? parseFloat(upper) : 1.0
|
||||||
|
jointInfo.step = 0.001
|
||||||
|
}
|
||||||
|
|
||||||
|
if (effort) jointInfo.maxEffort = parseFloat(effort)
|
||||||
|
if (velocity) jointInfo.maxVelocity = parseFloat(velocity)
|
||||||
|
} else {
|
||||||
|
// 如果没有限制,设置默认范围
|
||||||
|
if (type === 'continuous') {
|
||||||
|
jointInfo.min = -Math.PI
|
||||||
|
jointInfo.max = Math.PI
|
||||||
|
} else if (type === 'revolute') {
|
||||||
|
jointInfo.min = -Math.PI / 2
|
||||||
|
jointInfo.max = Math.PI / 2
|
||||||
|
} else if (type === 'prismatic') {
|
||||||
|
jointInfo.min = -0.5
|
||||||
|
jointInfo.max = 0.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取关节轴
|
||||||
|
const axisElements = jointElement.getElementsByTagName('axis')
|
||||||
|
if (axisElements.length > 0) {
|
||||||
|
const axis = axisElements[0].getAttribute('xyz')
|
||||||
|
if (axis) {
|
||||||
|
const axisValues = axis.split(' ').map(Number)
|
||||||
|
jointInfo.axis = new THREE.Vector3(...axisValues)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取关节原点
|
||||||
|
const originElements = jointElement.getElementsByTagName('origin')
|
||||||
|
if (originElements.length > 0) {
|
||||||
|
const origin = originElements[0]
|
||||||
|
const xyz = origin.getAttribute('xyz')
|
||||||
|
const rpy = origin.getAttribute('rpy')
|
||||||
|
|
||||||
|
if (xyz) jointInfo.origin = xyz.split(' ').map(Number)
|
||||||
|
if (rpy) jointInfo.orientation = rpy.split(' ').map(Number)
|
||||||
|
}
|
||||||
|
|
||||||
|
joints.push(jointInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按关节名称排序
|
||||||
|
joints.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
|
|
||||||
|
console.log('从URDF提取的关节信息:', joints)
|
||||||
|
return joints
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('解析URDF失败:', error)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化Three.js场景
|
||||||
|
*/
|
||||||
|
const initScene = () => {
|
||||||
|
const container = viewerContainer.value
|
||||||
|
|
||||||
|
scene = new THREE.Scene()
|
||||||
|
scene.background = new THREE.Color(0xf0f0f0)
|
||||||
|
|
||||||
|
camera = new THREE.PerspectiveCamera(
|
||||||
|
75,
|
||||||
|
container.clientWidth / container.clientHeight,
|
||||||
|
0.01,
|
||||||
|
1000
|
||||||
|
)
|
||||||
|
camera.position.set(2, 2, 3)
|
||||||
|
|
||||||
|
renderer = new THREE.WebGLRenderer({ antialias: true })
|
||||||
|
renderer.setSize(container.clientWidth, container.clientHeight)
|
||||||
|
container.appendChild(renderer.domElement)
|
||||||
|
|
||||||
|
// 光源
|
||||||
|
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6)
|
||||||
|
scene.add(ambientLight)
|
||||||
|
|
||||||
|
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8)
|
||||||
|
directionalLight.position.set(10, 20, 10)
|
||||||
|
scene.add(directionalLight)
|
||||||
|
|
||||||
|
controls = new OrbitControls(camera, renderer.domElement)
|
||||||
|
controls.enableDamping = true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载URDF机器人模型
|
||||||
|
*/
|
||||||
|
const loadRobot = async () => {
|
||||||
|
isLoading.value = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 清除现有模型
|
||||||
|
if (robot) {
|
||||||
|
scene.remove(robot)
|
||||||
|
jointControls.length = 0
|
||||||
|
availableJoints.value = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 加载URDF文件内容
|
||||||
|
const urdfUrl = `${props.basePath}${props.urdfPath}`
|
||||||
|
const response = await fetch(urdfUrl)
|
||||||
|
const urdfXml = await response.text()
|
||||||
|
|
||||||
|
// 2. 解析URDF提取关节信息(同步调用)
|
||||||
|
const extractedJoints = extractJointInfoFromURDF(urdfXml)
|
||||||
|
|
||||||
|
// 3. 使用URDFLoader加载模型
|
||||||
|
const manager = new THREE.LoadingManager()
|
||||||
|
const loader = new URDFLoader(manager)
|
||||||
|
|
||||||
|
loader.packages = { '': props.basePath }
|
||||||
|
|
||||||
|
robot = await new Promise((resolve, reject) => {
|
||||||
|
loader.load(urdfUrl, resolve, undefined, reject)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 4. 坐标轴修正
|
||||||
|
robot.rotation.x = -Math.PI / 2
|
||||||
|
robot.rotation.z = -Math.PI / 2
|
||||||
|
robot.updateMatrixWorld(true)
|
||||||
|
|
||||||
|
// 应用颜色
|
||||||
|
robot.traverse((child) => {
|
||||||
|
if (child.isMesh && child.material) {
|
||||||
|
child.material.color.set(props.modelColor)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
scene.add(robot)
|
||||||
|
|
||||||
|
// 5. 初始化关节控制系统
|
||||||
|
availableJoints.value = robot.joints
|
||||||
|
|
||||||
|
// 将提取的关节信息与加载的关节匹配
|
||||||
|
extractedJoints.forEach(jointInfo => {
|
||||||
|
if (availableJoints.value[jointInfo.name]) {
|
||||||
|
// 获取当前关节值
|
||||||
|
const currentValue = availableJoints.value[jointInfo.name].jointValue || 0
|
||||||
|
|
||||||
|
// 确保初始值在限制范围内
|
||||||
|
let initialValue = currentValue
|
||||||
|
if (props.showJointLimits) {
|
||||||
|
initialValue = Math.max(jointInfo.min, Math.min(jointInfo.max, currentValue))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加到控制列表
|
||||||
|
jointControls.push({
|
||||||
|
...jointInfo,
|
||||||
|
value: initialValue
|
||||||
|
})
|
||||||
|
|
||||||
|
// 设置初始关节位置
|
||||||
|
availableJoints.value[jointInfo.name].setJointValue(initialValue)
|
||||||
|
} else {
|
||||||
|
console.warn(`关节 ${jointInfo.name} 在URDF模型中不存在或不可控`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
fitCameraToObject(robot)
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载URDF模型失败:', error)
|
||||||
|
} finally {
|
||||||
|
isLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新关节角度
|
||||||
|
*/
|
||||||
|
const updateJointAngle = (jointName, angle) => {
|
||||||
|
if (availableJoints.value[jointName]) {
|
||||||
|
try {
|
||||||
|
// 应用限制(如果启用)
|
||||||
|
let clampedAngle = angle
|
||||||
|
if (props.showJointLimits) {
|
||||||
|
const jointInfo = jointControls.find(j => j.name === jointName)
|
||||||
|
if (jointInfo) {
|
||||||
|
clampedAngle = Math.max(jointInfo.min, Math.min(jointInfo.max, angle))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 应用关节角度
|
||||||
|
availableJoints.value[jointName].setJointValue(clampedAngle)
|
||||||
|
|
||||||
|
// 更新UI中的值
|
||||||
|
const jointControl = jointControls.find(j => j.name === jointName)
|
||||||
|
if (jointControl) {
|
||||||
|
jointControl.value = clampedAngle
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`设置关节 ${jointName} 角度失败:`, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调整相机视角
|
||||||
|
*/
|
||||||
|
const fitCameraToObject = (object) => {
|
||||||
|
const boundingBox = new THREE.Box3().setFromObject(object)
|
||||||
|
const center = boundingBox.getCenter(new THREE.Vector3())
|
||||||
|
const size = boundingBox.getSize(new THREE.Vector3())
|
||||||
|
|
||||||
|
const maxSize = Math.max(size.x, size.y, size.z)
|
||||||
|
const fitHeightDistance = maxSize / (2 * Math.atan((Math.PI * camera.fov) / 360))
|
||||||
|
const fitWidthDistance = fitHeightDistance / camera.aspect
|
||||||
|
const distance = 1.5 * Math.max(fitHeightDistance, fitWidthDistance)
|
||||||
|
|
||||||
|
const direction = new THREE.Vector3(0, 1, 1).normalize()
|
||||||
|
controls.target.copy(center)
|
||||||
|
camera.position.copy(center).add(direction.multiplyScalar(distance))
|
||||||
|
controls.update()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动画循环
|
||||||
|
*/
|
||||||
|
const animate = () => {
|
||||||
|
requestAnimationFrame(animate)
|
||||||
|
controls.update()
|
||||||
|
renderer.render(scene, camera)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 窗口大小变化处理
|
||||||
|
*/
|
||||||
|
const onWindowResize = () => {
|
||||||
|
const container = viewerContainer.value
|
||||||
|
camera.aspect = container.clientWidth / container.clientHeight
|
||||||
|
camera.updateProjectionMatrix()
|
||||||
|
renderer.setSize(container.clientWidth, container.clientHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理资源
|
||||||
|
*/
|
||||||
|
const dispose = () => {
|
||||||
|
window.removeEventListener('resize', onWindowResize)
|
||||||
|
controls?.dispose()
|
||||||
|
renderer?.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听属性变化
|
||||||
|
watch(
|
||||||
|
() => [props.basePath, props.urdfPath],
|
||||||
|
() => {
|
||||||
|
loadRobot()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(jointControls, (newVal) => {
|
||||||
|
emits('computedChange', newVal)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// 生命周期
|
||||||
|
onMounted(() => {
|
||||||
|
initScene()
|
||||||
|
loadRobot()
|
||||||
|
window.addEventListener('resize', onWindowResize)
|
||||||
|
animate()
|
||||||
|
})
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
dispose()
|
||||||
|
})
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
updateJointAngle
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 样式部分保持不变 */
|
||||||
|
.urdf-viewer-container {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.urdf-viewer {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.loading-overlay p {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #ecf0f1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,565 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import {useRoute} from "vue-router"
|
|
||||||
import dayjs from "dayjs";
|
|
||||||
import {deviceTeach, deviceUpdateProfile} from "@/api/device/register.js";
|
|
||||||
import {formatNumber} from "@/views/device/register/components/index.js";
|
|
||||||
import {convertNumbersToStringAndRemoveNulls} from "@/utils/fn.js";
|
|
||||||
|
|
||||||
const data = reactive({
|
|
||||||
form: {
|
|
||||||
workModule: 1,//工作模式
|
|
||||||
posStep: 1,//位置步进
|
|
||||||
postureStep: 1,//姿态步进
|
|
||||||
jointStep: 1,//关节步进
|
|
||||||
joint1: 0.000012,//关节1
|
|
||||||
joint2: 0.000012,//
|
|
||||||
joint3: 0.000012,//
|
|
||||||
joint4: 0.000012,//
|
|
||||||
joint5: 0.000012,//
|
|
||||||
joint6: 0.000012,//关节6
|
|
||||||
x: 11,//
|
|
||||||
y: 11,//
|
|
||||||
z: 11,//
|
|
||||||
rx: 11,//
|
|
||||||
ry: 11,//
|
|
||||||
rz: 11,//
|
|
||||||
arm: 1,//目标
|
|
||||||
coordinate: 1,//坐标系
|
|
||||||
},
|
|
||||||
speed: 20,//速度
|
|
||||||
zeroPos: {//零位姿态
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
z: 0,
|
|
||||||
rx: 0,
|
|
||||||
ry: 0,
|
|
||||||
rz: 0,
|
|
||||||
},
|
|
||||||
initPos: {
|
|
||||||
x: 1,
|
|
||||||
y: 1,
|
|
||||||
z: 1,
|
|
||||||
rx: 1,
|
|
||||||
ry: 1,
|
|
||||||
rz: 1,
|
|
||||||
},//初始姿态
|
|
||||||
armList: [
|
|
||||||
{
|
|
||||||
label: '机械臂1',
|
|
||||||
value: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '机械臂2',
|
|
||||||
value: 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
coordinateList: [
|
|
||||||
{
|
|
||||||
label: 'x轴',
|
|
||||||
value: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'y轴',
|
|
||||||
value: 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'z轴',
|
|
||||||
value: 3
|
|
||||||
}
|
|
||||||
],
|
|
||||||
time: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
|
||||||
})
|
|
||||||
|
|
||||||
const {
|
|
||||||
form, time,
|
|
||||||
zeroPos,
|
|
||||||
initPos,
|
|
||||||
armList,
|
|
||||||
coordinateList
|
|
||||||
} = toRefs(data)
|
|
||||||
|
|
||||||
const route = useRoute()
|
|
||||||
let timer = null
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
clearInterval(timer)
|
|
||||||
})
|
|
||||||
|
|
||||||
//获取机械臂参数
|
|
||||||
const getDeviceInfo = () => {
|
|
||||||
deviceTeach(devId.value).then((res) => {
|
|
||||||
let data = formatNumber(res.data)//字符类型转数字类型
|
|
||||||
Object.assign(form.value, data)
|
|
||||||
//设置初始位置
|
|
||||||
initPos.value.x = data.x
|
|
||||||
initPos.value.y = data.y
|
|
||||||
initPos.value.z = data.z
|
|
||||||
initPos.value.rx = data.rx
|
|
||||||
initPos.value.ry = data.ry
|
|
||||||
initPos.value.rz = data.rz
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
getDeviceInfo()
|
|
||||||
const posControls = document.querySelectorAll(".btn")
|
|
||||||
//监听按钮点击事件
|
|
||||||
posControls.forEach((item) => {
|
|
||||||
item.addEventListener('click', (e) => {
|
|
||||||
const target = e.currentTarget.classList[1]
|
|
||||||
const vals = target.split("_")//x_0 rx_0
|
|
||||||
const pos = vals[0]
|
|
||||||
const calc = !!Number(vals[1])
|
|
||||||
if (calc) {
|
|
||||||
form.value[pos] += 0.01 * data.speed
|
|
||||||
} else {
|
|
||||||
form.value[pos] -= 0.01 * data.speed
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
//监听失焦事件
|
|
||||||
// const warp = document.querySelector(".mechanical-arm")
|
|
||||||
// warp.addEventListener('focusout', handleFocus, false)
|
|
||||||
|
|
||||||
timer = setInterval(() => {
|
|
||||||
time.value = dayjs().format("YYYY-MM-DD HH:mm:ss")
|
|
||||||
getDeviceInfo()
|
|
||||||
}, 1000)
|
|
||||||
})
|
|
||||||
watch(() => JSON.parse(JSON.stringify(form.value)), (newData, oldData) => {
|
|
||||||
// const change = findDifferences(oldData, newData)
|
|
||||||
const data = convertNumbersToStringAndRemoveNulls(newData)
|
|
||||||
deviceUpdateProfile({idDeDeviceRegistration: devId.value, ...data}).then((res)=>{
|
|
||||||
console.log(res)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const handleFocus = (e) => {
|
|
||||||
const type = e.target.type
|
|
||||||
if (type === "number") {
|
|
||||||
// console.log("数字框失焦")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const devId = computed(() => {
|
|
||||||
return route.path.split("/")[2]
|
|
||||||
})
|
|
||||||
const deviceModel = computed(() => {
|
|
||||||
return route.path.split("/")[1]
|
|
||||||
})
|
|
||||||
|
|
||||||
const handleResets = (type) => {
|
|
||||||
if (type === "zero") {
|
|
||||||
Object.assign(form.value, zeroPos.value)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (type === "init") {
|
|
||||||
Object.assign(form.value, initPos.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="mechanical-arm">
|
|
||||||
<div class="top flex between">
|
|
||||||
<div class="left " style="width: 38%">
|
|
||||||
<div class="card" style="height: 100%">
|
|
||||||
<div class="title">机械臂</div>
|
|
||||||
<div class="body">机械臂图片</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="center" style="width: 22%">
|
|
||||||
<div class="card">
|
|
||||||
<div class="title">工作模式</div>
|
|
||||||
<div class="body">
|
|
||||||
<el-radio-group v-model="form.workModule">
|
|
||||||
<el-radio :value="1">真实机械臂</el-radio>
|
|
||||||
<el-radio :value="2">仿真机械臂</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card" style="margin-top: 10px">
|
|
||||||
<div class="title">步进模式</div>
|
|
||||||
<div class="mb10">
|
|
||||||
<div class="mb5 action-label">位置步进( mm )</div>
|
|
||||||
<el-input-number style="width: 100%;" v-model="form.posStep" :step="2"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb10">
|
|
||||||
<div class="mb5 action-label">姿态步进( deg )</div>
|
|
||||||
<el-input-number style="width: 100%;" v-model="form.postureStep" :step="2"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div class="mb5 action-label">关节步进( deg )</div>
|
|
||||||
<el-input-number style="width: 100%;" v-model="form.jointStep" :step="2"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="right " style="width: 38%">
|
|
||||||
<div class="card" style="height: 100%">
|
|
||||||
<div class="title">位置控制</div>
|
|
||||||
<div class="body">
|
|
||||||
<div class="btn-wrap pos-control" style="transform: rotateX(40deg);height: calc(100% - 70px)">
|
|
||||||
<div class="btn z_0">
|
|
||||||
<span>Z-</span>
|
|
||||||
<svg t="1747126605366" class="turn-bottom" viewBox="0 0 1024 1024" version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" p-id="1461" width="32" height="32">
|
|
||||||
<path
|
|
||||||
d="M311.432533 448.170667H163.84L510.293333 3.413333 856.746667 448.170667h-147.592534L760.832 1006.933333H259.754667z"
|
|
||||||
fill="#4076ff" p-id="1462"></path>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div class="btn x_0">
|
|
||||||
<span> X-</span>
|
|
||||||
<svg t="1747126605366" class="turn-up" viewBox="0 0 1024 1024" version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" p-id="1461" width="32" height="32">
|
|
||||||
<path
|
|
||||||
d="M311.432533 448.170667H163.84L510.293333 3.413333 856.746667 448.170667h-147.592534L760.832 1006.933333H259.754667z"
|
|
||||||
fill="#4076ff" p-id="1462"></path>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div class="btn z_1">
|
|
||||||
<span>Z+</span>
|
|
||||||
<svg t="1747126605366" class="turn-up" viewBox="0 0 1024 1024" version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" p-id="1461" width="32" height="32">
|
|
||||||
<path
|
|
||||||
d="M311.432533 448.170667H163.84L510.293333 3.413333 856.746667 448.170667h-147.592534L760.832 1006.933333H259.754667z"
|
|
||||||
fill="#4076ff" p-id="1462"></path>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div class="btn y_0">
|
|
||||||
<span>Y-</span>
|
|
||||||
<svg t="1747126605366" class="turn-left" viewBox="0 0 1024 1024" version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" p-id="1461" width="32" height="32">
|
|
||||||
<path
|
|
||||||
d="M311.432533 448.170667H163.84L510.293333 3.413333 856.746667 448.170667h-147.592534L760.832 1006.933333H259.754667z"
|
|
||||||
fill="#4076ff" p-id="1462"></path>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div class="btn"></div>
|
|
||||||
<div class="btn y_1">
|
|
||||||
<span>Y+</span>
|
|
||||||
<svg t="1747126605366" class="turn-right" viewBox="0 0 1024 1024" version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" p-id="1461" width="32" height="32">
|
|
||||||
<path
|
|
||||||
d="M311.432533 448.170667H163.84L510.293333 3.413333 856.746667 448.170667h-147.592534L760.832 1006.933333H259.754667z"
|
|
||||||
fill="#4076ff" p-id="1462"></path>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div class="btn"></div>
|
|
||||||
<div class="btn x_1">
|
|
||||||
<span>X+</span>
|
|
||||||
<svg t="1747126605366" class="turn-bottom" viewBox="0 0 1024 1024" version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" p-id="1461" width="32" height="32">
|
|
||||||
<path
|
|
||||||
d="M311.432533 448.170667H163.84L510.293333 3.413333 856.746667 448.170667h-147.592534L760.832 1006.933333H259.754667z"
|
|
||||||
fill="#4076ff" p-id="1462"></path>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div class="btn"></div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="mb10 action-label">参考坐标系</div>
|
|
||||||
<el-select
|
|
||||||
|
|
||||||
v-model="form.coordinate"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item in coordinateList"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="bottom flex between">
|
|
||||||
<div class="left " style="width: 30%">
|
|
||||||
<div class="card" style="height: 100%">
|
|
||||||
<div class="title">机械臂位置姿态</div>
|
|
||||||
<div class="body">
|
|
||||||
<div class="flex mb10">
|
|
||||||
<div class="left flex1">
|
|
||||||
<div class="pos-title mb10">位置 ( m )</div>
|
|
||||||
<div class="mb10"> X: {{ form.x.toFixed(6) }}</div>
|
|
||||||
<div class="mb10"> Y: {{ form.y.toFixed(6) }}</div>
|
|
||||||
<div class="mb10"> Z: {{ form.z.toFixed(6) }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="right flex1">
|
|
||||||
<div class="pos-title mb10">姿态 ( deg )</div>
|
|
||||||
<div class="mb10"> RX: {{ form.rx.toFixed(6) }}</div>
|
|
||||||
<div class="mb10"> RY: {{ form.ry.toFixed(6) }}</div>
|
|
||||||
<div class="mb10"> RZ: {{ form.rz.toFixed(6) }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="mb10 action-label">目标</div>
|
|
||||||
<el-select
|
|
||||||
v-model="form.arm"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item in armList"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="center " style="width: 30%">
|
|
||||||
<div class="card" style="height: 100%">
|
|
||||||
<div class="title">关节控制单位( deg )</div>
|
|
||||||
<div class="body">
|
|
||||||
<div class="mb10 action-label-pos">
|
|
||||||
<div class="action-label">关节1</div>
|
|
||||||
<el-input-number v-model="form.joint1" :step="0.000001" :precision="6"/>
|
|
||||||
</div>
|
|
||||||
<div class="mb10 action-label-pos">
|
|
||||||
<div class="action-label">关节2</div>
|
|
||||||
<el-input-number v-model="form.joint2" :step="0.000001" :precision="6"/>
|
|
||||||
</div>
|
|
||||||
<div class="mb10 action-label-pos">
|
|
||||||
<div class="action-label">关节3</div>
|
|
||||||
<el-input-number v-model="form.joint3" :step="0.000001" :precision="6"/>
|
|
||||||
</div>
|
|
||||||
<div class="mb10 action-label-pos">
|
|
||||||
<div class="action-label">关节4</div>
|
|
||||||
<el-input-number v-model="form.joint4" :step="0.000001" :precision="6"/>
|
|
||||||
</div>
|
|
||||||
<div class="mb10 action-label-pos">
|
|
||||||
<div class="action-label">关节5</div>
|
|
||||||
<el-input-number v-model="form.joint5" :step="0.000001" :precision="6"/>
|
|
||||||
</div>
|
|
||||||
<div class="mb10 action-label-pos">
|
|
||||||
<div class="action-label">关节6</div>
|
|
||||||
<el-input-number v-model="form.joint6" :step="0.000001" :precision="6"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="right " style="width: 38%">
|
|
||||||
<div class="card" style="height: 100%">
|
|
||||||
<div class="title">姿态控制</div>
|
|
||||||
<div class="body">
|
|
||||||
<div class="btn-wrap">
|
|
||||||
<div class="btn rz_0 c">
|
|
||||||
<span>Z-</span>
|
|
||||||
<svg t="1747126605366" class="turn-lb" viewBox="0 0 1024 1024" version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" p-id="1461" width="32" height="32">
|
|
||||||
<path
|
|
||||||
d="M311.432533 448.170667H163.84L510.293333 3.413333 856.746667 448.170667h-147.592534L760.832 1006.933333H259.754667z"
|
|
||||||
fill="#4076ff" p-id="1462"></path>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div class="btn rx_0 c">
|
|
||||||
<span>X-</span>
|
|
||||||
<svg t="1747126605366" class="turn-up" viewBox="0 0 1024 1024" version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" p-id="1461" width="32" height="32">
|
|
||||||
<path
|
|
||||||
d="M311.432533 448.170667H163.84L510.293333 3.413333 856.746667 448.170667h-147.592534L760.832 1006.933333H259.754667z"
|
|
||||||
fill="#4076ff" p-id="1462"></path>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div class="btn rz_1 c">
|
|
||||||
<span>Z+</span>
|
|
||||||
<svg t="1747126605366" class="turn-rb" viewBox="0 0 1024 1024" version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" p-id="1461" width="32" height="32">
|
|
||||||
<path
|
|
||||||
d="M311.432533 448.170667H163.84L510.293333 3.413333 856.746667 448.170667h-147.592534L760.832 1006.933333H259.754667z"
|
|
||||||
fill="#4076ff" p-id="1462"></path>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div class="btn ry_0 c">
|
|
||||||
<span> Y-</span>
|
|
||||||
<svg t="1747126605366" class="turn-left" viewBox="0 0 1024 1024" version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" p-id="1461" width="32" height="32">
|
|
||||||
<path
|
|
||||||
d="M311.432533 448.170667H163.84L510.293333 3.413333 856.746667 448.170667h-147.592534L760.832 1006.933333H259.754667z"
|
|
||||||
fill="#4076ff" p-id="1462"></path>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div class="btn"></div>
|
|
||||||
<div class="btn ry_1 c">
|
|
||||||
<span>Y+</span>
|
|
||||||
<svg t="1747126605366" class="turn-right" viewBox="0 0 1024 1024" version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" p-id="1461" width="32" height="32">
|
|
||||||
<path
|
|
||||||
d="M311.432533 448.170667H163.84L510.293333 3.413333 856.746667 448.170667h-147.592534L760.832 1006.933333H259.754667z"
|
|
||||||
fill="#4076ff" p-id="1462"></path>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div class="btn"></div>
|
|
||||||
<div class="btn rx_1 c">
|
|
||||||
<span> X+</span>
|
|
||||||
<svg t="1747126605366" class="turn-bottom" viewBox="0 0 1024 1024" version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" p-id="1461" width="32" height="32">
|
|
||||||
<path
|
|
||||||
d="M311.432533 448.170667H163.84L510.293333 3.413333 856.746667 448.170667h-147.592534L760.832 1006.933333H259.754667z"
|
|
||||||
fill="#4076ff" p-id="1462"></path>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div class="btn"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="actions flex align-center between">
|
|
||||||
<div class="left">
|
|
||||||
<el-button @click="handleResets('zero')">零位姿态</el-button>
|
|
||||||
<el-button @click="handleResets('init')">初始位姿</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="center">
|
|
||||||
{{ time }}
|
|
||||||
</div>
|
|
||||||
<div class="right flex align-center">
|
|
||||||
<div style="width: 100px;user-select: none">速度</div>
|
|
||||||
<el-slider size="small" :show-tooltip="false" v-model="data.speed"/>
|
|
||||||
<div style="margin-left: 20px"> {{ data.speed }}%</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.mechanical-arm {
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.top {
|
|
||||||
padding: 10px 10px 0;
|
|
||||||
height: 48%;
|
|
||||||
|
|
||||||
.center {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
.card:last-child {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.bottom {
|
|
||||||
padding: 0 10px;
|
|
||||||
height: 44%;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
|
||||||
height: 6%;
|
|
||||||
box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
|
|
||||||
padding: 0 10px;
|
|
||||||
|
|
||||||
.right {
|
|
||||||
width: 300px;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.center {
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-label {
|
|
||||||
color: #606266;
|
|
||||||
font-size: 14px;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-label-pos {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.el-input-number {
|
|
||||||
width: calc(100% - 50px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 1px solid #e4e7ed;
|
|
||||||
padding: 10px;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
color: #333;
|
|
||||||
font-size: 14px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
font-weight: 900;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.body {
|
|
||||||
height: calc(100% - 29px);
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
.pos-title {
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-wrap {
|
|
||||||
height: 100%;
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(3, 1fr);
|
|
||||||
grid-template-rows: repeat(3, 1fr);
|
|
||||||
justify-items: center;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
span {
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
svg {
|
|
||||||
width: 60px;
|
|
||||||
height: 60px;
|
|
||||||
transform-origin: center center;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.turn-lb {
|
|
||||||
transform: rotate(-135deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.turn-rb {
|
|
||||||
transform: rotate(135deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.turn-left {
|
|
||||||
transform: rotate(-90deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.turn-right {
|
|
||||||
transform: rotate(90deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.turn-bottom {
|
|
||||||
transform: rotate(-180deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,28 +1,10 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { reactive, toRefs, onMounted, onUnmounted, watch, computed, ref } from "vue";
|
import { reactive, toRefs, onUnmounted, ref, onMounted } from "vue";
|
||||||
import { useRoute } from "vue-router";
|
import UrdfViewer from "./components/UrdfViewer.vue";
|
||||||
import dayjs from "dayjs";
|
import JointControl from "./components/JointControl.vue";
|
||||||
import { deviceTeach } from "@/api/device/register.js";
|
|
||||||
import { formatNumber } from "@/views/device/register/components/index.js";
|
|
||||||
import { convertNumbersToStringAndRemoveNulls } from "@/utils/fn.js";
|
|
||||||
import {
|
|
||||||
moveJ,
|
|
||||||
status
|
|
||||||
} from '@/api/device/arm';
|
|
||||||
|
|
||||||
const data = reactive({
|
const data = reactive({
|
||||||
form: {
|
form: {
|
||||||
workModule: 1,
|
|
||||||
posStep: 1,
|
|
||||||
postureStep: 1,
|
|
||||||
jointStep: 1,
|
|
||||||
joint1: 0.000012,
|
|
||||||
joint2: 0.000012,
|
|
||||||
joint3: 0.000012,
|
|
||||||
joint4: 0.000012,
|
|
||||||
joint5: 0.000012,
|
|
||||||
joint6: 0.000012,
|
|
||||||
joint7: 0.000012,
|
|
||||||
x: 11,
|
x: 11,
|
||||||
y: 11,
|
y: 11,
|
||||||
z: 11,
|
z: 11,
|
||||||
@ -30,207 +12,153 @@ const data = reactive({
|
|||||||
ry: 11,
|
ry: 11,
|
||||||
rz: 11,
|
rz: 11,
|
||||||
arm: 1,
|
arm: 1,
|
||||||
coordinate: 1,
|
|
||||||
},
|
|
||||||
speed: 20,
|
|
||||||
zeroPos: {
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
z: 0,
|
|
||||||
rx: 0,
|
|
||||||
ry: 0,
|
|
||||||
rz: 0,
|
|
||||||
},
|
|
||||||
initPos: {
|
|
||||||
x: 1,
|
|
||||||
y: 1,
|
|
||||||
z: 1,
|
|
||||||
rx: 1,
|
|
||||||
ry: 1,
|
|
||||||
rz: 1,
|
|
||||||
},
|
},
|
||||||
armList: [
|
armList: [
|
||||||
{ label: '目标1', value: 1 },
|
{ label: "目标1", value: 1 },
|
||||||
{ label: '目标2', value: 2 },
|
{ label: "目标2", value: 2 },
|
||||||
{ label: '目标3', value: 3 },
|
{ label: "目标3", value: 3 },
|
||||||
],
|
],
|
||||||
time: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
|
||||||
});
|
});
|
||||||
const terminalId = ref('25449ff3fcc7b27da5f69462c5efcec2');
|
|
||||||
const deviceId = ref('spk1');
|
const { form, armList } = toRefs(data);
|
||||||
const { form, time, zeroPos, initPos, armList } = toRefs(data);
|
|
||||||
const route = useRoute();
|
const leftJointList = ref(null);
|
||||||
|
const rightJointList = ref(null);
|
||||||
|
const computedChange = (val) => {
|
||||||
|
leftJointList.value = val.filter((item) => {
|
||||||
|
return item.name[0] === "L";
|
||||||
|
});
|
||||||
|
rightJointList.value = val.filter((item) => {
|
||||||
|
return item.name[0] === "R";
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const urdfViewerRef = ref(null);
|
||||||
|
|
||||||
|
const updateJointAngle = ({ name, value }) => {
|
||||||
|
if (urdfViewerRef.value) {
|
||||||
|
urdfViewerRef.value.updateJointAngle(name, value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const coordinateSystem = ref(null); // 用于获取容器元素
|
const coordinateSystem = ref(null); // 用于获取容器元素
|
||||||
const buttonPositions = ref([]); // 存储按钮的动态位置
|
const buttonPositions = ref([]); // 存储按钮的动态位置
|
||||||
|
|
||||||
// 调整后的原始坐标(基于默认图片尺寸 1025x817px)
|
const buttonDirections = [
|
||||||
const initialPositions = [
|
{ target: "z_plus", direction: "top", label: "Z+" }, // left
|
||||||
{ target: "z_plus", x: 500, y: 80, label: "Z+" },
|
{ target: "rz_plus", direction: "top-right", label: "RZ+" },
|
||||||
{ target: "rz_plus", x: 675, y: 124, label: "RZ+" },
|
{ target: "x_plus", direction: "right", label: "X+" }, // bottom
|
||||||
{ target: "x_plus", x: 796, y: 245, label: "X+" },
|
{ target: "ry_plus", direction: "bottom-right", label: "RY+" },
|
||||||
{ target: "ry_plus", x: 840, y: 410, label: "RY+" },
|
{ target: "y_minus", direction: "bottom", label: "Y-" },
|
||||||
{ target: "y_minus", x: 796, y: 570, label: "Y-" },
|
{ target: "ry_minus", direction: "bottom-left", label: "RY-" },
|
||||||
{ target: "ry_minus", x: 675, y: 696, label: "RY-" },
|
{ target: "z_minus", direction: "bottom", label: "Z-" },
|
||||||
{ target: "z_minus", x: 500, y: 745, label: "Z-" },
|
{ target: "rx_minus", direction: "bottom-left", label: "RX-" },
|
||||||
{ target: "rx_minus", x: 345, y: 696, label: "RX-" },
|
{ target: "x_minus", direction: "left", label: "X-" },
|
||||||
{ target: "x_minus", x: 206, y: 570, label: "X-" },
|
{ target: "rx_plus", direction: "top-left", label: "RX+" },
|
||||||
{ target: "rx_plus", x: 180, y: 410, label: "RX+" },
|
{ target: "y_plus", direction: "left", label: "Y+" }, // right
|
||||||
{ target: "y_plus", x: 204, y: 245, label: "Y+" },
|
{ target: "rz_minus", direction: "top-left", label: "RZ-" },
|
||||||
{ target: "rz_minus", x: 345, y: 124, label: "RZ-" },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// 默认图片尺寸
|
// 默认图片尺寸
|
||||||
const ORIGINAL_IMAGE_WIDTH = 1025;
|
const ORIGINAL_IMAGE_WIDTH = 1025;
|
||||||
const ORIGINAL_IMAGE_HEIGHT = 817;
|
const ORIGINAL_IMAGE_HEIGHT = 817;
|
||||||
|
|
||||||
let timer = null;
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
clearInterval(timer);
|
|
||||||
});
|
|
||||||
|
|
||||||
const getDeviceInfo = () => {
|
|
||||||
deviceTeach(devId.value).then((res) => {
|
|
||||||
let dataRes = formatNumber(res.data);
|
|
||||||
Object.assign(form.value, dataRes);
|
|
||||||
initPos.value.x = dataRes.x;
|
|
||||||
initPos.value.y = dataRes.y;
|
|
||||||
initPos.value.z = dataRes.z;
|
|
||||||
initPos.value.rx = dataRes.rx;
|
|
||||||
initPos.value.ry = dataRes.ry;
|
|
||||||
initPos.value.rz = dataRes.rz;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateButtonPositions = () => {
|
const updateButtonPositions = () => {
|
||||||
if (coordinateSystem.value) {
|
if (coordinateSystem.value) {
|
||||||
const { width, height } = coordinateSystem.value.getBoundingClientRect();
|
const containerRect = coordinateSystem.value.getBoundingClientRect();
|
||||||
// 计算图片的实际显示尺寸(考虑 background-size: contain)
|
const containerWidth = containerRect.width;
|
||||||
const imageAspectRatio = ORIGINAL_IMAGE_WIDTH / ORIGINAL_IMAGE_HEIGHT; // 1025 / 817 ≈ 1.255
|
const containerHeight = containerRect.height;
|
||||||
const containerAspectRatio = width / height;
|
|
||||||
|
|
||||||
let imageWidth, imageHeight, offsetX, offsetY;
|
// 计算图片的实际显示尺寸(考虑 background-size: contain)
|
||||||
|
const imageAspectRatio = ORIGINAL_IMAGE_WIDTH / ORIGINAL_IMAGE_HEIGHT;
|
||||||
|
const containerAspectRatio = containerWidth / containerHeight;
|
||||||
|
|
||||||
|
let imageWidth, imageHeight, imageLeft, imageTop;
|
||||||
if (containerAspectRatio > imageAspectRatio) {
|
if (containerAspectRatio > imageAspectRatio) {
|
||||||
// 容器较宽,高度限制图片大小,上下有留白
|
imageHeight = containerHeight;
|
||||||
imageHeight = height;
|
imageWidth = imageHeight * imageAspectRatio;
|
||||||
imageWidth = height * imageAspectRatio;
|
imageLeft = (containerWidth - imageWidth) / 2;
|
||||||
offsetX = (width - imageWidth) / 2; // 水平居中
|
imageTop = 0;
|
||||||
offsetY = 0; // 顶部对齐
|
|
||||||
} else {
|
} else {
|
||||||
// 容器较窄,宽度限制图片大小,左右有留白
|
imageWidth = containerWidth;
|
||||||
imageWidth = width;
|
imageHeight = imageWidth / imageAspectRatio;
|
||||||
imageHeight = width / imageAspectRatio;
|
imageLeft = 0;
|
||||||
offsetX = 0; // 左对齐
|
imageTop = (containerHeight - imageHeight) / 2;
|
||||||
offsetY = (height - imageHeight) / 2; // 垂直居中
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算缩放比例(基于图片实际显示尺寸)
|
// 计算图片中心坐标
|
||||||
const scaleX = imageWidth / ORIGINAL_IMAGE_WIDTH;
|
const centerX = imageLeft + imageWidth / 2;
|
||||||
const scaleY = imageHeight / ORIGINAL_IMAGE_HEIGHT;
|
const centerY = imageTop + imageHeight / 2;
|
||||||
|
|
||||||
|
// 计算圆的半径(根据图片尺寸的较小值比例确定,可调整比例系数)
|
||||||
|
const radiusScale = 0.85; // 半径系数,0-1之间,越大半径越大
|
||||||
|
const radius = Math.min(imageWidth, imageHeight) * radiusScale / 2;
|
||||||
|
|
||||||
|
// 定义方位对应的角度(弧度制),top为0度,顺时针增加
|
||||||
|
const directionAngles = {
|
||||||
|
"top": 0,
|
||||||
|
"top-right": Math.PI / 6, // 30度
|
||||||
|
"right": Math.PI / 3, // 60度
|
||||||
|
"bottom-right": Math.PI / 2, // 90度
|
||||||
|
"bottom": 2 * Math.PI / 3, // 120度
|
||||||
|
"bottom-left": 5 * Math.PI / 6, // 150度
|
||||||
|
"left": Math.PI, // 180度
|
||||||
|
"top-left": 7 * Math.PI / 6, // 210度
|
||||||
|
};
|
||||||
|
|
||||||
|
// 调整角度以均匀分布12个按钮(360/12=30度,即Math.PI/6弧度)
|
||||||
|
const totalButtons = buttonDirections.length;
|
||||||
|
const angleStep = 2 * Math.PI / totalButtons;
|
||||||
|
|
||||||
// 更新按钮位置
|
// 更新按钮位置
|
||||||
buttonPositions.value = initialPositions.map((pos) => ({
|
buttonPositions.value = buttonDirections.map((btn, index) => {
|
||||||
...pos,
|
// 计算每个按钮的角度(从top开始顺时针排列)
|
||||||
left: pos.x * scaleX + offsetX, // 按比例缩放 x 坐标并加上水平偏移
|
const angle = index * angleStep;
|
||||||
top: pos.y * scaleY + offsetY, // 按比例缩放 y 坐标并加上垂直偏移
|
// 计算按钮的坐标
|
||||||
}));
|
const x = centerX + radius * Math.sin(angle);
|
||||||
|
const y = centerY - radius * Math.cos(angle);
|
||||||
|
return {
|
||||||
|
...btn,
|
||||||
|
left: x,
|
||||||
|
top: y,
|
||||||
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getDeviceInfo();
|
|
||||||
// 初始计算按钮位置
|
|
||||||
updateButtonPositions();
|
updateButtonPositions();
|
||||||
// 添加按钮事件监听
|
|
||||||
const posControls = document.querySelectorAll(".pos-btn");
|
|
||||||
posControls.forEach((item) => {
|
|
||||||
item.addEventListener('click', (e) => {
|
|
||||||
const target = e.currentTarget.dataset.target;
|
|
||||||
const [pos, direction] = target.split("_");
|
|
||||||
const step = (pos === 'x' || pos === 'y' || pos === 'z') ? form.value.posStep : form.value.postureStep;
|
|
||||||
const delta = direction === 'plus' ? step : -step;
|
|
||||||
form.value[pos] += delta * (data.speed / 100);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// 监听窗口大小变化,更新按钮位置
|
// 监听窗口大小变化,更新按钮位置
|
||||||
window.addEventListener('resize', updateButtonPositions);
|
window.addEventListener("resize", updateButtonPositions);
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
window.removeEventListener('resize', updateButtonPositions);
|
window.removeEventListener("resize", updateButtonPositions);
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(() => JSON.parse(JSON.stringify(form.value)), (newData) => {
|
|
||||||
const dataToSend = convertNumbersToStringAndRemoveNulls(newData);
|
|
||||||
moveJ({
|
|
||||||
"deviceId": deviceId.value,
|
|
||||||
"terminalId": terminalId.value,
|
|
||||||
"acc": 0.8,
|
|
||||||
"vel": 0.8,
|
|
||||||
"cmds": [
|
|
||||||
{
|
|
||||||
"jointName": "R_SHOULDER_P",
|
|
||||||
"rad": dataToSend.joint1,
|
|
||||||
"vel": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"jointName": "R_SHOULDER_R",
|
|
||||||
"rad": dataToSend.joint2,
|
|
||||||
"vel": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"jointName": "R_SHOULDER_Y",
|
|
||||||
"rad": dataToSend.joint3,
|
|
||||||
"vel": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"jointName": "R_ELBOW_R",
|
|
||||||
"rad": dataToSend.joint4,
|
|
||||||
"vel": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"jointName": "R_WRIST_P",
|
|
||||||
"rad": dataToSend.joint5,
|
|
||||||
"vel": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"jointName": "R_WRIST_Y",
|
|
||||||
"rad": dataToSend.joint6,
|
|
||||||
"vel": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"jointName": "R_WRIST_R",
|
|
||||||
"rad": dataToSend.joint7,
|
|
||||||
"vel": 1.0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
const devId = computed(() => {
|
|
||||||
return route.path.split("/")[2];
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleResets = (type) => {
|
|
||||||
if (type === "zero") {
|
|
||||||
Object.assign(form.value, zeroPos.value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (type === "init") {
|
|
||||||
Object.assign(form.value, initPos.value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="mechanical-arm">
|
<div class="mechanical-arm">
|
||||||
<div class="top card">
|
<div class="top card">
|
||||||
<div class="controls flex align-center" style="justify-content: flex-start;">
|
<div class="controls flex align-center" style="justify-content: flex-start">
|
||||||
<div class="control-label">目标</div>
|
<div class="control-label">目标</div>
|
||||||
<el-select v-model="form.arm" placeholder="选择目标" style="width: 100px; margin-right: 20px;">
|
<el-select
|
||||||
<el-option v-for="item in armList" :key="item.value" :label="item.label" :value="item.value" />
|
v-model="form.arm"
|
||||||
|
placeholder="选择目标"
|
||||||
|
style="width: 100px; margin-right: 20px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in armList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
<el-button @click="handleResets('zero')" style="margin-right: 10px;">零位姿态</el-button>
|
<el-button @click="handleResets('zero')" style="margin-right: 10px"
|
||||||
|
>零位姿态</el-button
|
||||||
|
>
|
||||||
<el-button @click="handleResets('init')">初始位置</el-button>
|
<el-button @click="handleResets('init')">初始位置</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="pose-info flex align-center">
|
<div class="pose-info flex align-center">
|
||||||
@ -242,69 +170,52 @@ const handleResets = (type) => {
|
|||||||
<div class="pose-item">RZ: {{ form.rz.toFixed(6) }} deg</div>
|
<div class="pose-item">RZ: {{ form.rz.toFixed(6) }} deg</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bottom flex">
|
<div class="bottom">
|
||||||
<div class="left card" style="flex: 1; position: relative;">
|
<div class="left">
|
||||||
<div class="title">姿态与位置控制</div>
|
<UrdfViewer
|
||||||
<div class="coordinate-system" ref="coordinateSystem">
|
ref="urdfViewerRef"
|
||||||
<div class="control-buttons">
|
:base-path="'/public/models/'"
|
||||||
<button
|
:urdf-path="'dual_arm.urdf'"
|
||||||
v-for="(pos, index) in buttonPositions"
|
:model-color="'#8a8ae9'"
|
||||||
:key="index"
|
@computedChange="computedChange"
|
||||||
class="pos-btn"
|
/>
|
||||||
:data-target="pos.target"
|
</div>
|
||||||
:style="{ left: `${pos.left}px`, top: `${pos.top}px` }"
|
<div class="right">
|
||||||
>
|
<div class="top">
|
||||||
{{ pos.label }}
|
<div class="secondary-title">
|
||||||
</button>
|
<div class="label">左手</div>
|
||||||
|
<div class="label">右手</div>
|
||||||
|
</div>
|
||||||
|
<div class="jointControl-container">
|
||||||
|
<JointControl
|
||||||
|
:jointList="leftJointList"
|
||||||
|
@updateJointAngle="updateJointAngle"
|
||||||
|
/>
|
||||||
|
<JointControl
|
||||||
|
:jointList="rightJointList"
|
||||||
|
@updateJointAngle="updateJointAngle"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="bottom">
|
||||||
<div class="right card" style="flex: 1;">
|
<div class="left card" style="position: relative">
|
||||||
<div class="title">关节控制 (deg)</div>
|
<div class="coordinate-system" ref="coordinateSystem">
|
||||||
<div class="input-list">
|
<div class="control-buttons">
|
||||||
<div class="input-item">
|
<button
|
||||||
<span>关节1</span>
|
v-for="(pos, index) in buttonPositions"
|
||||||
<el-input-number v-model="form.joint1" :step="form.jointStep" :precision="6" />
|
:key="index"
|
||||||
</div>
|
class="pos-btn"
|
||||||
<div class="input-item">
|
:data-target="pos.target"
|
||||||
<span>关节2</span>
|
:style="{ left: `${pos.left}px`, top: `${pos.top}px` }"
|
||||||
<el-input-number v-model="form.joint2" :step="form.jointStep" :precision="6" />
|
>
|
||||||
</div>
|
{{ pos.label }}
|
||||||
<div class="input-item">
|
</button>
|
||||||
<span>关节3</span>
|
</div>
|
||||||
<el-input-number v-model="form.joint3" :step="form.jointStep" :precision="6" />
|
</div>
|
||||||
</div>
|
|
||||||
<div class="input-item">
|
|
||||||
<span>关节4</span>
|
|
||||||
<el-input-number v-model="form.joint4" :step="form.jointStep" :precision="6" />
|
|
||||||
</div>
|
|
||||||
<div class="input-item">
|
|
||||||
<span>关节5</span>
|
|
||||||
<el-input-number v-model="form.joint5" :step="form.jointStep" :precision="6" />
|
|
||||||
</div>
|
|
||||||
<div class="input-item">
|
|
||||||
<span>关节6</span>
|
|
||||||
<el-input-number v-model="form.joint6" :step="form.jointStep" :precision="6" />
|
|
||||||
</div>
|
|
||||||
<div class="input-item">
|
|
||||||
<span>关节7</span>
|
|
||||||
<el-input-number v-model="form.joint7" :step="form.jointStep" :precision="6" />
|
|
||||||
</div>
|
|
||||||
<div class="input-item">
|
|
||||||
<span>关节步进</span>
|
|
||||||
<el-input-number v-model="form.jointStep" :step="0.1" :precision="1" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer card flex align-center between">
|
|
||||||
<div class="time">{{ time }}</div>
|
|
||||||
<div class="speed flex align-center">
|
|
||||||
<span>速度</span>
|
|
||||||
<el-slider v-model="data.speed" :min="0" :max="100" style="width: 200px; margin: 0 10px;" />
|
|
||||||
<span>{{ data.speed }}%</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -341,97 +252,99 @@ const handleResets = (type) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.bottom {
|
.bottom {
|
||||||
flex: 1;
|
height: calc(100% - 120px);
|
||||||
gap: 20px;
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
.title {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.left {
|
.left {
|
||||||
display: flex;
|
flex: 2;
|
||||||
flex-direction: column;
|
height: 100%;
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.coordinate-system {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
position: relative;
|
|
||||||
background-color: #FFF;
|
|
||||||
background-image: url('@/assets/images/arm.png');
|
|
||||||
background-size: contain;
|
|
||||||
background-position: center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
|
|
||||||
.control-buttons {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
|
|
||||||
.pos-btn {
|
|
||||||
position: absolute;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
background: #4076ff;
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 16px;
|
|
||||||
border-radius: 4px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
transform: translate(-50%, -50%); /* 按钮中心对齐坐标 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.right {
|
.right {
|
||||||
.input-list {
|
flex: 1;
|
||||||
display: flex;
|
height: 100%;
|
||||||
flex-direction: column;
|
display: flex;
|
||||||
gap: 10px;
|
flex-direction: column;
|
||||||
|
|
||||||
.input-item {
|
.top {
|
||||||
|
flex: 1;
|
||||||
|
border: 1px solid #e4e7ed;
|
||||||
|
padding: 0 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.container-title {
|
||||||
|
font-size: 16px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secondary-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
justify-content: space-around;
|
||||||
justify-content: space-between;
|
padding: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
span {
|
.jointControl-container {
|
||||||
width: 80px;
|
display: flex;
|
||||||
user-select: none;
|
gap: 10px;
|
||||||
}
|
height: calc(100% - 75px);
|
||||||
|
overflow: auto;
|
||||||
.el-input-number {
|
|
||||||
width: calc(100% - 90px);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
.bottom {
|
||||||
height: 50px;
|
flex: 1;
|
||||||
|
|
||||||
.time {
|
.card {
|
||||||
font-size: 14px;
|
border: 1px solid #e4e7ed;
|
||||||
}
|
border-radius: 8px;
|
||||||
|
padding: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
.speed {
|
.coordinate-system {
|
||||||
gap: 10px;
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
background-color: #fff;
|
||||||
|
background-image: url("@/assets/images/arm.png");
|
||||||
|
background-size: contain;
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
|
||||||
span {
|
.control-buttons {
|
||||||
user-select: none;
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
.pos-btn {
|
||||||
|
position: absolute;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background: #4076ff;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transform: translate(-50%, -50%); /* 按钮中心对齐坐标 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user