机型配置

This commit is contained in:
ywb
2026-05-14 22:53:06 +08:00
parent fdb88b21a1
commit e14ee07a84
4 changed files with 334 additions and 54 deletions
+210 -42
View File
@@ -209,48 +209,6 @@
"poses": [] "poses": []
} }
}, },
{
"id": "m_3_4",
"row": 3,
"col": 4,
"front": {
"coords": [
0,
0,
0
],
"poses": []
},
"back": {
"coords": [
0,
0,
0
],
"poses": []
}
},
{
"id": "m_3_3",
"row": 3,
"col": 3,
"front": {
"coords": [
0,
0,
0
],
"poses": []
},
"back": {
"coords": [
0,
0,
0
],
"poses": []
}
},
{ {
"id": "m_0_1", "id": "m_0_1",
"row": 0, "row": 0,
@@ -334,5 +292,215 @@
], ],
"poses": [] "poses": []
} }
},
{
"id": "m_0_3",
"row": 0,
"col": 3,
"front": {
"coords": [
0,
0,
0
],
"poses": []
},
"back": {
"coords": [
0,
0,
0
],
"poses": []
}
},
{
"id": "m_0_4",
"row": 0,
"col": 4,
"front": {
"coords": [
0,
0,
0
],
"poses": []
},
"back": {
"coords": [
0,
0,
0
],
"poses": []
}
},
{
"id": "m_0_5",
"row": 0,
"col": 5,
"front": {
"coords": [
0,
0,
0
],
"poses": []
},
"back": {
"coords": [
0,
0,
0
],
"poses": []
}
},
{
"id": "m_1_3",
"row": 1,
"col": 3,
"front": {
"coords": [
0,
0,
0
],
"poses": []
},
"back": {
"coords": [
0,
0,
0
],
"poses": []
}
},
{
"id": "m_1_5",
"row": 1,
"col": 5,
"front": {
"coords": [
0,
0,
0
],
"poses": []
},
"back": {
"coords": [
0,
0,
0
],
"poses": []
}
},
{
"id": "m_1_4",
"row": 1,
"col": 4,
"front": {
"coords": [
0,
0,
0
],
"poses": []
},
"back": {
"coords": [
0,
0,
0
],
"poses": []
}
},
{
"id": "m_2_3",
"row": 2,
"col": 3,
"front": {
"coords": [
0,
0,
0
],
"poses": []
},
"back": {
"coords": [
0,
0,
0
],
"poses": []
}
},
{
"id": "m_2_1",
"row": 2,
"col": 1,
"front": {
"coords": [
0,
0,
0
],
"poses": []
},
"back": {
"coords": [
0,
0,
0
],
"poses": []
}
},
{
"id": "m_2_4",
"row": 2,
"col": 4,
"front": {
"coords": [
0,
0,
0
],
"poses": []
},
"back": {
"coords": [
0,
0,
0
],
"poses": []
}
},
{
"id": "m_2_5",
"row": 2,
"col": 5,
"front": {
"coords": [
0,
0,
0
],
"poses": []
},
"back": {
"coords": [
0,
0,
0
],
"poses": []
}
} }
] ]
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"rows": 2, "rows": 4,
"cols": 2, "cols": 6,
"grid": [], "grid": [],
"positions": [ "positions": [
{ {
+97
View File
@@ -29,6 +29,7 @@ const app = createApp({
models: [], models: [],
selectedModelId: null, selectedModelId: null,
newModelName: '', newModelName: '',
newModelId: null,
newModelDesc: '', newModelDesc: '',
newModelNotes: '', newModelNotes: '',
newPoseForm: {}, // 机型配置:新建姿态的表单 newPoseForm: {}, // 机型配置:新建姿态的表单
@@ -211,6 +212,7 @@ const app = createApp({
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ body: JSON.stringify({
name: this.newModelName || '型号_' + (this.models.length + 1), name: this.newModelName || '型号_' + (this.models.length + 1),
id: this.newModelId,
description: this.newModelDesc || '', description: this.newModelDesc || '',
notes: this.newModelNotes || '', notes: this.newModelNotes || '',
serial_prefix: this.newModelSerial || '' serial_prefix: this.newModelSerial || ''
@@ -831,6 +833,101 @@ const app = createApp({
onPreviewError(e) { onPreviewError(e) {
e.target.style.display = 'none' e.target.style.display = 'none'
}, },
// === 姿态角度控制(机型配置 Tab) ===
async refreshPoseAngles(modelId, poseId) {
// 获取当前机械臂角度,填入姿态,保存到后端
if (!this.armConnected) {
alert('机械臂未连接')
return
}
try {
var res = await fetch(API + '/api/arm/get_angles')
var data = await res.json()
if (data.ok && data.angles) {
// Find the pose and update
var model = this.models.find(m => m.id === modelId)
if (model) {
var pose = model.poses.find(p => p.id === poseId)
if (pose) {
pose.arm_angles = [...data.angles]
// Save to backend
await fetch(API + '/api/models/' + modelId + '/poses/' + poseId, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ arm_angles: pose.arm_angles })
})
}
}
}
} catch (e) {
console.error('refreshPoseAngles error:', e)
}
},
async applyPoseAngles(modelId, poseId) {
// 调整机械臂到姿态的角度
var model = this.models.find(m => m.id === modelId)
if (model) {
var pose = model.poses.find(p => p.id === poseId)
if (pose && pose.arm_angles) {
try {
await fetch(API + '/api/arm/set_angles', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ angles: pose.arm_angles, speed: 500 })
})
} catch (e) {
console.error('applyPoseAngles error:', e)
}
}
}
},
async adjustPoseAngle(modelId, poseId, jointIndex, delta) {
// 微调姿态角度,并实时调整机械臂
var model = this.models.find(m => m.id === modelId)
if (model) {
var pose = model.poses.find(p => p.id === poseId)
if (pose) {
if (!pose.arm_angles) pose.arm_angles = [0, 0, 0, 0, 0, 0]
pose.arm_angles[jointIndex] = (pose.arm_angles[jointIndex] || 0) + delta
// Save to backend
await fetch(API + '/api/models/' + modelId + '/poses/' + poseId, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ arm_angles: pose.arm_angles })
})
// Move arm
await fetch(API + '/api/arm/set_angle', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ joint: 'J' + (jointIndex + 1), angle: pose.arm_angles[jointIndex] })
})
}
}
},
async updatePoseAngleAndMove(modelId, poseId, jointIndex, value) {
// 更新姿态角度(输入框),并实时调整机械臂
var model = this.models.find(m => m.id === modelId)
if (model) {
var pose = model.poses.find(p => p.id === poseId)
if (pose) {
if (!pose.arm_angles) pose.arm_angles = [0, 0, 0, 0, 0, 0]
pose.arm_angles[jointIndex] = parseFloat(value) || 0
// Save to backend
await fetch(API + '/api/models/' + modelId + '/poses/' + poseId, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ arm_angles: pose.arm_angles })
})
// Move arm
await fetch(API + '/api/arm/set_angle', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ joint: 'J' + (jointIndex + 1), angle: pose.arm_angles[jointIndex] })
})
}
}
},
// === AGV 控制 === // === AGV 控制 ===
async refreshAgvPosition() { async refreshAgvPosition() {
if (!this.agvConnected) return if (!this.agvConnected) return
+25 -10
View File
@@ -4,7 +4,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>设置 - AGV 拍摄系统</title> <title>设置 - AGV 拍摄系统</title>
<link rel="stylesheet" href="/static/css/style.css?v=20260514l"> <link rel="stylesheet" href="/static/css/style.css?v=20260514m">
</head> </head>
<body> <body>
<div id="app"> <div id="app">
@@ -78,6 +78,10 @@
<label>机型名称</label> <label>机型名称</label>
<input type="text" v-model="newModelName" placeholder="例如:SMT-A" style="width:100%;padding:8px;border:1px solid #2a3441;border-radius:4px"> <input type="text" v-model="newModelName" placeholder="例如:SMT-A" style="width:100%;padding:8px;border:1px solid #2a3441;border-radius:4px">
</div> </div>
<div class="form-group" style="flex:1">
<label>机型ID(数值)</label>
<input type="number" v-model.number="newModelId" placeholder="例如:100" style="width:100%;padding:8px;border:1px solid #2a3441;border-radius:4px">
</div>
</div> </div>
<div class="form-row"> <div class="form-row">
<div class="form-group" style="flex:1"> <div class="form-group" style="flex:1">
@@ -121,14 +125,20 @@
<button class="btn btn-danger btn-small" @click="deletePose(m.id, pose.id)">删除</button> <button class="btn btn-danger btn-small" @click="deletePose(m.id, pose.id)">删除</button>
</div> </div>
<div style="display:flex;gap:8px;flex-wrap:wrap"> <div style="display:flex;gap:8px;flex-wrap:wrap">
<div v-for="j in 6" :key="j" style="display:flex;align-items:center;gap:4px"> <div v-for="j in 6" :key="j" style="display:flex;align-items:center;gap:4px">
<span style="font-size:12px;color:#9aa0a6">J{% raw %}{ j }{% endraw %}</span> <span style="font-size:12px;color:#9aa0a6">J{% raw %}{ j }{% endraw %}</span>
<input type="number" step="0.1" <button class="btn btn-small" @click="adjustPoseAngle(m.id, pose.id, j-1, -0.5)" style="width:24px;height:24px;padding:0;font-size:12px">-</button>
<input type="number" step="0.5"
:value="pose.arm_angles && pose.arm_angles[j-1] !== undefined ? pose.arm_angles[j-1] : 0" :value="pose.arm_angles && pose.arm_angles[j-1] !== undefined ? pose.arm_angles[j-1] : 0"
@change="updatePoseAngle(m.id, pose.id, j-1, $event.target.value)" @change="updatePoseAngleAndMove(m.id, pose.id, j-1, $event.target.value)"
style="width:70px;padding:4px;border:1px solid #2a3441;border-radius:4px"> style="width:70px;padding:4px;border:1px solid #2a3441;border-radius:4px">
<button class="btn btn-small" @click="adjustPoseAngle(m.id, pose.id, j-1, 0.5)" style="width:24px;height:24px;padding:0;font-size:12px">+</button>
<span style="font-size:11px;color:#999">°</span> <span style="font-size:11px;color:#999">°</span>
</div> </div>
<div style="margin-top:8px;display:flex;gap:8px">
<button class="btn btn-secondary btn-small" @click="refreshPoseAngles(m.id, pose.id)">🔄 刷新角度</button>
<button class="btn btn-primary btn-small" @click="applyPoseAngles(m.id, pose.id)">✅ 应用角度</button>
</div>
</div> </div>
</div> </div>
<!-- 添加正面姿态 --> <!-- 添加正面姿态 -->
@@ -163,14 +173,20 @@
<button class="btn btn-danger btn-small" @click="deletePose(m.id, pose.id)">删除</button> <button class="btn btn-danger btn-small" @click="deletePose(m.id, pose.id)">删除</button>
</div> </div>
<div style="display:flex;gap:8px;flex-wrap:wrap"> <div style="display:flex;gap:8px;flex-wrap:wrap">
<div v-for="j in 6" :key="j" style="display:flex;align-items:center;gap:4px"> <div v-for="j in 6" :key="j" style="display:flex;align-items:center;gap:4px">
<span style="font-size:12px;color:#9aa0a6">J{% raw %}{ j }{% endraw %}</span> <span style="font-size:12px;color:#9aa0a6">J{% raw %}{ j }{% endraw %}</span>
<input type="number" step="0.1" <button class="btn btn-small" @click="adjustPoseAngle(m.id, pose.id, j-1, -0.5)" style="width:24px;height:24px;padding:0;font-size:12px">-</button>
<input type="number" step="0.5"
:value="pose.arm_angles && pose.arm_angles[j-1] !== undefined ? pose.arm_angles[j-1] : 0" :value="pose.arm_angles && pose.arm_angles[j-1] !== undefined ? pose.arm_angles[j-1] : 0"
@change="updatePoseAngle(m.id, pose.id, j-1, $event.target.value)" @change="updatePoseAngleAndMove(m.id, pose.id, j-1, $event.target.value)"
style="width:70px;padding:4px;border:1px solid #2a3441;border-radius:4px"> style="width:70px;padding:4px;border:1px solid #2a3441;border-radius:4px">
<button class="btn btn-small" @click="adjustPoseAngle(m.id, pose.id, j-1, 0.5)" style="width:24px;height:24px;padding:0;font-size:12px">+</button>
<span style="font-size:11px;color:#999">°</span> <span style="font-size:11px;color:#999">°</span>
</div> </div>
<div style="margin-top:8px;display:flex;gap:8px">
<button class="btn btn-secondary btn-small" @click="refreshPoseAngles(m.id, pose.id)">🔄 刷新角度</button>
<button class="btn btn-primary btn-small" @click="applyPoseAngles(m.id, pose.id)">✅ 应用角度</button>
</div>
</div> </div>
</div> </div>
<!-- 添加背面姿态 --> <!-- 添加背面姿态 -->
@@ -439,7 +455,6 @@
<button @mousedown="jogStart(j-1, 1)" @mouseup="jogStop(j-1)" @mouseleave="jogStop(j-1)"></button> <button @mousedown="jogStart(j-1, 1)" @mouseup="jogStop(j-1)" @mouseleave="jogStop(j-1)"></button>
</div> </div>
</div> </div>
</div>
<div class="btn-row"> <div class="btn-row">
<button class="btn btn-primary" @click="refreshAngles">🔄 刷新角度</button> <button class="btn btn-primary" @click="refreshAngles">🔄 刷新角度</button>
<button class="btn btn-secondary" @click="applyAngles">✅ 应用角度</button> <button class="btn btn-secondary" @click="applyAngles">✅ 应用角度</button>
@@ -505,7 +520,7 @@
</main> </main>
</div> </div>
<script src="/static/js/vue3.global.prod.js?v=20260514l"></script> <script src="/static/js/vue3.global.prod.js?v=20260514m"></script>
<script src="/static/js/setting.js?v=20260514l"></script> <script src="/static/js/setting.js?v=20260514m"></script>
</body> </body>
</html> </html>