From 8035cf29e2814e99ef704d483fc7b1e792c3132e Mon Sep 17 00:00:00 2001 From: ywb <347742090@qq.com> Date: Fri, 29 May 2026 20:21:46 +0800 Subject: [PATCH] - --- agv_app/static/js/setting.js | 42 +++++++++++++++++++++++++++++-- agv_app/templates/setting.html | 1 + agv_app/utils/mission_executor.py | 19 +++++++------- 3 files changed, 50 insertions(+), 12 deletions(-) diff --git a/agv_app/static/js/setting.js b/agv_app/static/js/setting.js index 0e96518..9c9d43b 100644 --- a/agv_app/static/js/setting.js +++ b/agv_app/static/js/setting.js @@ -857,13 +857,51 @@ createApp({ body: JSON.stringify({ joint: 'J' + (idx + 1), angle: val }) }) }, - async applyAngles() { + async applyAngles(angles = null) { + const targetAngles = angles || this.angleInputs await fetch(API + '/api/arm/set_angles', { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ angles: this.angleInputs, speed: 500 }) + body: JSON.stringify({ angles: targetAngles, speed: 500 }) }) }, + }, + async invertAngles() { + // 每个角度取反:10 → -10, -10 → 10 + const inverted = this.angleInputs.map(a => -a) + + // 🔍 角度范围检查(myCobot 630 限位) + const limits = [ + [-180, 180], // J1 + [-90, 90], // J2 + [-90, 90], // J3 + [-180, 180], // J4 + [-90, 90], // J5 + [-180, 180] // J6 + ] + const outOfRange = [] + for (let i = 0; i < 6; i++) { + if (inverted[i] < limits[i][0] || inverted[i] > limits[i][1]) { + outOfRange.push('J' + (i+1) + '=' + inverted[i].toFixed(1) + '° (范围: ' + limits[i][0] + '~' + limits[i][1] + '°)') + } + } + if (outOfRange.length > 0) { + alert('⚠️ 角度超出范围:\n' + outOfRange.join('\n')) + return // 不执行反转 + } + + // 应用到机械臂 + try { + await this.applyAngles(inverted) + this.angleInputs = inverted // 只有在成功后才更新显示 + alert('✅ 角度已反转并应用') + } catch (e) { + alert('❌ 应用失败: ' + e.message) + } + + // 等待2秒让机械臂到位,然后刷新显示 + setTimeout(() => this.refreshAngles(), 2000) + }, jogStart(idx, dir) { const joint = 'J' + (idx + 1) fetch(API + '/api/arm/jog', { diff --git a/agv_app/templates/setting.html b/agv_app/templates/setting.html index 7118c93..d0a0430 100644 --- a/agv_app/templates/setting.html +++ b/agv_app/templates/setting.html @@ -510,6 +510,7 @@
+
diff --git a/agv_app/utils/mission_executor.py b/agv_app/utils/mission_executor.py index c1b1d3d..824b904 100644 --- a/agv_app/utils/mission_executor.py +++ b/agv_app/utils/mission_executor.py @@ -781,7 +781,7 @@ class MissionExecutorV3: def _capture_arm_photo(self, row: int, col: int, side: str, pose_idx: int, qr_value: str, upload_index: int = 0) -> Optional[str]: - """从机械臂摄像头拍照存本地,然后上传到服务器 + """从机械臂摄像头拍照,直接上传到服务器(不保存本地) upload_index: 从1开始,先正面后背面,由调用方维护 """ @@ -791,21 +791,17 @@ class MissionExecutorV3: logger.error("arm snapshot 请求失败") return None - os.makedirs(PHOTOS_DIR, exist_ok=True) + # 生成文件名(用于上传) ts = time.strftime("%Y%m%d_%H%M%S") fname = f"{ts}_r{row}c{col}_{side}_p{pose_idx}_{qr_value[:20]}.jpg" - fpath = os.path.join(PHOTOS_DIR, fname) - with open(fpath, "wb") as f: - f.write(resp.content) - self._log(f" 💾 本地保存: {os.path.basename(fpath)}") - # 上传到服务器 + # 直接上传到服务器(不保存本地) if qr_value: - self._upload_photo(fpath, qr_value, upload_index) + self._upload_photo_bytes(fname, resp.content, qr_value, upload_index) else: self._log(" ⚠️ 无二维码,跳过上传") - return fpath + return fname # 返回文件名(用于日志) except Exception as e: logger.error(f"拍照异常: {e}") return None @@ -820,10 +816,13 @@ class MissionExecutorV3: """ try: filename = os.path.basename(filepath) + headers = { + "Authorization": "Bearer eyJhbGciOiJIUzUxMiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VyX2tleSI6ImZhNTNkZTZiLWE3NjYtNDZmNC05MDUyLTQ2MjUzZTAyNjdmNSIsInVzZXJuYW1lIjoiYWRtaW4ifQ.lC4vKThZo4aAOLsekm2kPgaEJRqRx-YDQWKfHFqxdPNESCKy57l3eIqaKTj2ZjAMaoYAwYlMrv5M1zAOJsO_PA" + } with open(filepath, "rb") as f: files = {"file": (filename, f, "image/jpeg")} data = {"serialNumber": serial_number, "index": str(index)} - resp = requests.post(UPLOAD_URL, files=files, data=data, timeout=30) + resp = requests.post(UPLOAD_URL, files=files, data=data, headers=headers, timeout=30) if resp.status_code == 200: self._log(f" ☁️ 上传成功 [{index}]: {filename}") return True