feat:修改机械臂
This commit is contained in:
parent
e7986ec2eb
commit
001ac86310
18
src/api/device/arm.js
Normal file
18
src/api/device/arm.js
Normal file
@ -0,0 +1,18 @@
|
||||
import request from '@/utils/request'
|
||||
// 移动机械臂
|
||||
export function moveJ(data) {
|
||||
return request({
|
||||
url: '/api/humanoid/moveJ',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取机械臂状态
|
||||
export function status(data) {
|
||||
return request({
|
||||
url: '/api/humanoid/status',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
BIN
src/assets/images/arm.png
Normal file
BIN
src/assets/images/arm.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
@ -1,10 +1,14 @@
|
||||
<script setup>
|
||||
import { reactive, toRefs, onMounted, onUnmounted, watch, computed } from "vue";
|
||||
import { reactive, toRefs, onMounted, onUnmounted, watch, computed, ref } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import dayjs from "dayjs";
|
||||
import { deviceTeach, deviceUpdateProfile } from "@/api/device/register.js";
|
||||
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({
|
||||
form: {
|
||||
@ -18,6 +22,7 @@ const data = reactive({
|
||||
joint4: 0.000012,
|
||||
joint5: 0.000012,
|
||||
joint6: 0.000012,
|
||||
joint7: 0.000012,
|
||||
x: 11,
|
||||
y: 11,
|
||||
z: 11,
|
||||
@ -51,10 +56,33 @@ const data = reactive({
|
||||
],
|
||||
time: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
||||
});
|
||||
|
||||
const terminalId = ref('25449ff3fcc7b27da5f69462c5efcec2');
|
||||
const deviceId = ref('spk1');
|
||||
const { form, time, zeroPos, initPos, armList } = toRefs(data);
|
||||
|
||||
const route = useRoute();
|
||||
const coordinateSystem = ref(null); // 用于获取容器元素
|
||||
const buttonPositions = ref([]); // 存储按钮的动态位置
|
||||
|
||||
// 调整后的原始坐标(基于默认图片尺寸 1025x817px)
|
||||
const initialPositions = [
|
||||
{ target: "z_plus", x: 500, y: 80, label: "Z+" },
|
||||
{ target: "rz_plus", x: 675, y: 124, label: "RZ+" },
|
||||
{ target: "x_plus", x: 796, y: 245, label: "X+" },
|
||||
{ target: "ry_plus", x: 840, y: 410, label: "RY+" },
|
||||
{ target: "y_minus", x: 796, y: 570, label: "Y-" },
|
||||
{ target: "ry_minus", x: 675, y: 696, label: "RY-" },
|
||||
{ target: "z_minus", x: 500, y: 745, label: "Z-" },
|
||||
{ target: "rx_minus", x: 345, y: 696, label: "RX-" },
|
||||
{ target: "x_minus", x: 206, y: 570, label: "X-" },
|
||||
{ target: "rx_plus", x: 180, y: 410, label: "RX+" },
|
||||
{ target: "y_plus", x: 204, y: 245, label: "Y+" },
|
||||
{ target: "rz_minus", x: 345, y: 124, label: "RZ-" },
|
||||
];
|
||||
|
||||
// 默认图片尺寸
|
||||
const ORIGINAL_IMAGE_WIDTH = 1025;
|
||||
const ORIGINAL_IMAGE_HEIGHT = 817;
|
||||
|
||||
let timer = null;
|
||||
|
||||
onUnmounted(() => {
|
||||
@ -74,8 +102,46 @@ const getDeviceInfo = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const updateButtonPositions = () => {
|
||||
if (coordinateSystem.value) {
|
||||
const { width, height } = coordinateSystem.value.getBoundingClientRect();
|
||||
// 计算图片的实际显示尺寸(考虑 background-size: contain)
|
||||
const imageAspectRatio = ORIGINAL_IMAGE_WIDTH / ORIGINAL_IMAGE_HEIGHT; // 1025 / 817 ≈ 1.255
|
||||
const containerAspectRatio = width / height;
|
||||
|
||||
let imageWidth, imageHeight, offsetX, offsetY;
|
||||
if (containerAspectRatio > imageAspectRatio) {
|
||||
// 容器较宽,高度限制图片大小,上下有留白
|
||||
imageHeight = height;
|
||||
imageWidth = height * imageAspectRatio;
|
||||
offsetX = (width - imageWidth) / 2; // 水平居中
|
||||
offsetY = 0; // 顶部对齐
|
||||
} else {
|
||||
// 容器较窄,宽度限制图片大小,左右有留白
|
||||
imageWidth = width;
|
||||
imageHeight = width / imageAspectRatio;
|
||||
offsetX = 0; // 左对齐
|
||||
offsetY = (height - imageHeight) / 2; // 垂直居中
|
||||
}
|
||||
|
||||
// 计算缩放比例(基于图片实际显示尺寸)
|
||||
const scaleX = imageWidth / ORIGINAL_IMAGE_WIDTH;
|
||||
const scaleY = imageHeight / ORIGINAL_IMAGE_HEIGHT;
|
||||
|
||||
// 更新按钮位置
|
||||
buttonPositions.value = initialPositions.map((pos) => ({
|
||||
...pos,
|
||||
left: pos.x * scaleX + offsetX, // 按比例缩放 x 坐标并加上水平偏移
|
||||
top: pos.y * scaleY + offsetY, // 按比例缩放 y 坐标并加上垂直偏移
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getDeviceInfo();
|
||||
// 初始计算按钮位置
|
||||
updateButtonPositions();
|
||||
// 添加按钮事件监听
|
||||
const posControls = document.querySelectorAll(".pos-btn");
|
||||
posControls.forEach((item) => {
|
||||
item.addEventListener('click', (e) => {
|
||||
@ -86,13 +152,59 @@ onMounted(() => {
|
||||
form.value[pos] += delta * (data.speed / 100);
|
||||
});
|
||||
});
|
||||
// 监听窗口大小变化,更新按钮位置
|
||||
window.addEventListener('resize', updateButtonPositions);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', updateButtonPositions);
|
||||
});
|
||||
|
||||
watch(() => JSON.parse(JSON.stringify(form.value)), (newData) => {
|
||||
const dataToSend = convertNumbersToStringAndRemoveNulls(newData);
|
||||
deviceUpdateProfile({ idDeDeviceRegistration: devId.value, ...dataToSend }).then((res) => {
|
||||
console.log(res);
|
||||
});
|
||||
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(() => {
|
||||
@ -131,87 +243,20 @@ const handleResets = (type) => {
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom flex">
|
||||
<div class="left card" style="flex: 1;">
|
||||
<div class="left card" style="flex: 1; position: relative;">
|
||||
<div class="title">姿态与位置控制</div>
|
||||
<div class="coordinate-system" ref="coordinateSystem">
|
||||
<div class="control-buttons">
|
||||
<div class="axis-controls flex">
|
||||
<div class="axis-group">
|
||||
<span>X: {{ form.x.toFixed(6) }} m</span>
|
||||
<button class="pos-btn" data-target="x_minus">-</button>
|
||||
<button class="pos-btn" data-target="x_plus">+</button>
|
||||
</div>
|
||||
<div class="axis-group">
|
||||
<span>Y: {{ form.y.toFixed(6) }} m</span>
|
||||
<button class="pos-btn" data-target="y_minus">-</button>
|
||||
<button class="pos-btn" data-target="y_plus">+</button>
|
||||
</div>
|
||||
<div class="axis-group">
|
||||
<span>Z: {{ form.z.toFixed(6) }} m</span>
|
||||
<button class="pos-btn" data-target="z_minus">-</button>
|
||||
<button class="pos-btn" data-target="z_plus">+</button>
|
||||
</div>
|
||||
<div class="axis-group">
|
||||
<span>RX: {{ form.rx.toFixed(6) }} deg</span>
|
||||
<button class="pos-btn rotation" data-target="rx_minus">
|
||||
<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="20" height="20">
|
||||
<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>
|
||||
</button>
|
||||
<button class="pos-btn rotation" data-target="rx_plus">
|
||||
<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="20" height="20">
|
||||
<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>
|
||||
<button
|
||||
v-for="(pos, index) in buttonPositions"
|
||||
:key="index"
|
||||
class="pos-btn"
|
||||
:data-target="pos.target"
|
||||
:style="{ left: `${pos.left}px`, top: `${pos.top}px` }"
|
||||
>
|
||||
{{ pos.label }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="axis-group">
|
||||
<span>RY: {{ form.ry.toFixed(6) }} deg</span>
|
||||
<button class="pos-btn rotation" data-target="ry_minus">
|
||||
<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="20" height="20">
|
||||
<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>
|
||||
</button>
|
||||
<button class="pos-btn rotation" data-target="ry_plus">
|
||||
<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="20" height="20">
|
||||
<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>
|
||||
</button>
|
||||
</div>
|
||||
<div class="axis-group">
|
||||
<span>RZ: {{ form.rz.toFixed(6) }} deg</span>
|
||||
<button class="pos-btn rotation" data-target="rz_minus">
|
||||
<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="20" height="20">
|
||||
<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>
|
||||
</button>
|
||||
<button class="pos-btn rotation" data-target="rz_plus">
|
||||
<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="20" height="20">
|
||||
<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>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="coordinate-system">
|
||||
<svg width="400" height="400" viewBox="0 0 400 400" class="coordinate-svg">
|
||||
<!-- X axis (positive) -->
|
||||
<line x1="200" y1="200" x2="350" y2="200" stroke="#f00" stroke-width="4" />
|
||||
<text x="360" y="205" fill="#f00">X</text>
|
||||
<!-- X axis (negative) -->
|
||||
<line x1="200" y1="200" x2="50" y2="200" stroke="#f00" stroke-width="4" />
|
||||
<text x="40" y="205" fill="#f00">-X</text>
|
||||
<!-- Y axis (positive) -->
|
||||
<line x1="200" y1="200" x2="200" y2="50" stroke="#0f0" stroke-width="4" />
|
||||
<text x="195" y="40" fill="#0f0">Y</text>
|
||||
<!-- Y axis (negative) -->
|
||||
<line x1="200" y1="200" x2="200" y2="350" stroke="#0f0" stroke-width="4" />
|
||||
<text x="195" y="360" fill="#0f0">-Y</text>
|
||||
<!-- Z axis (positive) -->
|
||||
<line x1="200" y1="200" x2="300" y2="100" stroke="#00f" stroke-width="4" />
|
||||
<text x="305" y="95" fill="#00f">Z</text>
|
||||
<!-- Z axis (negative) -->
|
||||
<line x1="200" y1="200" x2="100" y2="300" stroke="#00f" stroke-width="4" />
|
||||
<text x="95" y="305" fill="#00f">-Z</text>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right card" style="flex: 1;">
|
||||
@ -241,6 +286,10 @@ const handleResets = (type) => {
|
||||
<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" />
|
||||
@ -305,30 +354,31 @@ const handleResets = (type) => {
|
||||
.left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
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 {
|
||||
margin-bottom: 20px;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
.axis-controls {
|
||||
justify-content: space-around;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
|
||||
.axis-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
min-width: 150px;
|
||||
|
||||
span {
|
||||
width: 80px;
|
||||
text-align: center;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
.pos-btn {
|
||||
position: absolute;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: #4076ff;
|
||||
color: white;
|
||||
border: none;
|
||||
@ -338,48 +388,8 @@ const handleResets = (type) => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transform: translate(-50%, -50%); /* 按钮中心对齐坐标 */
|
||||
}
|
||||
|
||||
.rotation svg {
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
.turn-up {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
.turn-bottom {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.turn-left {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
.turn-right {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.turn-lb {
|
||||
transform: rotate(-135deg);
|
||||
}
|
||||
|
||||
.turn-rb {
|
||||
transform: rotate(135deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.coordinate-system {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.coordinate-svg {
|
||||
background: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user