From e8da4a76a81dce29710e700c097ee371743c9efc Mon Sep 17 00:00:00 2001 From: JayJiaJun Date: Tue, 18 Mar 2025 17:32:30 +0800 Subject: [PATCH] 3.18 --- src/assets/js/GamepadController.js | 218 ++++++++++++----------------- src/views/CarControl.vue | 129 ++++++++++++----- src/views/ConeControl.vue | 94 ++++++++++--- vue.config.js | 1 + 4 files changed, 261 insertions(+), 181 deletions(-) diff --git a/src/assets/js/GamepadController.js b/src/assets/js/GamepadController.js index 4de644b..ffcdaa8 100644 --- a/src/assets/js/GamepadController.js +++ b/src/assets/js/GamepadController.js @@ -1,151 +1,111 @@ class GamepadController { constructor(options = {}) { - this.options = { + this.options = { ...{ debug: false, deadZone: 0.1, - updateInterval: 50, - buttonsConfig: [ - { name: "Left2", index: 6 }, - { name: "Back", index: 8 }, - { name: "Right Joystick Press", index: 11 } - ] + updateInterval: 50 }, - ...options + ...options }; - - this.gamepadIndex = null; - this.gamepad = null; - this.interval = null; - this.buttons = []; - this.directionAxis0_1 = ""; - this.directionAxis9 = ""; - this.angle = 0; + + this.gamepadIndex = null; + this.gamepad = null; + this.interval = null; + this.angle = 0; // 这里将存储 0-360 的角度值 + this.speed = 0; + this.directionAxis9 = 0; this.rightJoystickPressed = false; - this.speed = 0; // 添加速度属性 - // 初始化按钮状态 - this.buttons = this.options.buttonsConfig.map(button => ({ - ...button, - pressed: false - })); - - // 注册事件监听器 - window.addEventListener("gamepadconnected", this.onGamepadConnected.bind(this)); - window.addEventListener("gamepaddisconnected", this.onGamepadDisconnected.bind(this)); - - if (this.options.debug) { - console.log("GamepadController initialized with options:", this.options); - } + this.isActive = false; + + this.updateLoop = setInterval(() => this.update(), this.options.updateInterval); } - - onGamepadConnected(e) { - console.log("Gamepad connected:", e.gamepad); - this.gamepadIndex = e.gamepad.index; - this.gamepad = navigator.getGamepads()[this.gamepadIndex]; - this.startGamepad(); - } - - onGamepadDisconnected() { - clearInterval(this.interval); - this.gamepad = null; - if (this.options.debug) { - console.log("Gamepad disconnected"); - } - } - - startGamepad() { - this.interval = setInterval(() => { - const gamepads = navigator.getGamepads(); - const gamepad = gamepads[this.gamepadIndex]; - - if (gamepad) { - // 注释掉调试打印 - // if (this.options.debug) { - // console.log('Axes data:', { - // axis0: gamepad.axes[0], - // axis1: gamepad.axes[1], - // gamepadIndex: this.gamepadIndex - // }); - // } - - this.updateDirection(gamepad.axes); - this.updateDirectionAxis9(gamepad.axes); - this.pressKey(gamepad.buttons); - } - }, this.options.updateInterval); - } - - updateDirection(axes) { - const axis0 = axes[0]; - const axis1 = axes[1]; - - // 检查是否在死区 - if (Math.abs(axis0) < this.options.deadZone && Math.abs(axis1) < this.options.deadZone) { - this.directionAxis0_1 = "未定义"; - this.angle = 0; - this.speed = 0; // 在死区时速度为0 + + update() { + const gamepad = navigator.getGamepads()[0]; + if (!gamepad) { + this.isActive = false; return; } - - // 计算速度(到原点的距离) - // 使用勾股定理计算距离,并将结果限制在0-100之间 - const distance = Math.sqrt(axis0 * axis0 + axis1 * axis1); - this.speed = Math.round(Math.min(distance * 100, 100)); - // 计算方向角度(0-360度) - let angle = Math.atan2(axis1, axis0) * (180 / Math.PI); - angle = (angle + 360) % 360; - angle = Math.round(angle); - this.angle = angle; + this.isActive = true; - // 更新方向数据 - if (Math.abs(axis0) > this.options.deadZone || Math.abs(axis1) > this.options.deadZone) { - this.directionAxis0_1 = `${angle}°`; - // 注释掉调试打印 - // if (this.options.debug) { - // console.log(` 摇杆方向: ${angle}°, X轴: ${axis0.toFixed(2)}, Y轴: ${axis1.toFixed(2)}`); - // } + // 获取左摇杆的值 + const x = gamepad.axes[0]; + const y = gamepad.axes[1]; + + // 应用死区 + const absX = Math.abs(x); + const absY = Math.abs(y); + + if (absX < this.options.deadZone && absY < this.options.deadZone) { + this.angle = 0; + this.speed = 0; + } else { + this.updateDirection(gamepad.axes); + } + + // 获取右摇杆的值(用于云台控制) + const rightY = gamepad.axes[3]; + if (Math.abs(rightY) > this.options.deadZone) { + this.directionAxis9 = rightY > 0 ? 1 : 2; + } else { + this.directionAxis9 = 0; + } + + // 更新右摇杆按钮状态 + this.rightJoystickPressed = gamepad.buttons[10].pressed; + + if (this.options.debug) { + console.log('GamepadController 状态:', { + x: x.toFixed(2), + y: y.toFixed(2), + angle: this.angle, + speed: this.speed.toFixed(2), + directionAxis9: this.directionAxis9, + rightJoystickPressed: this.rightJoystickPressed + }); } } - - updateDirectionAxis9(axes) { - const axis9 = axes[9]; - const roundedAxis9 = Math.round(axis9 * 100) / 100; - if (roundedAxis9 <= -0.9) { - this.directionAxis9 = 1; - } else if (roundedAxis9 >= 0.0 && roundedAxis9 <= 0.2) { - this.directionAxis9 = 2; - // } else if (roundedAxis9 >= 0.6 && roundedAxis9 <= 0.8) { - // this.directionAxis9 = "左"; - // } else if (roundedAxis9 >= -0.5 && roundedAxis9 <= -0.4) { - // this.directionAxis9 = "右"; - } - else { - this.directionAxis9 = 0; + + updateDirection(axes) { + const axis0 = axes[0]; // X轴 + const axis1 = axes[1]; // Y轴 + + // 检查是否在死区 + if (Math.abs(axis0) < this.options.deadZone && Math.abs(axis1) < this.options.deadZone) { + this.angle = 0; + this.speed = 0; + return; + } + + // 计算角度(0-360度),从x轴正半轴开始顺时针旋转 + let angle = Math.atan2(axis1, axis0) * (180 / Math.PI); + // 将角度转换到 0-360 范围 + if (angle < 0) { + angle += 360; + } + this.angle = Math.round(angle); + + // 计算速度(0-100) + const distance = Math.sqrt(axis0 * axis0 + axis1 * axis1); + this.speed = Math.min(Math.round(distance * 100), 100); + + if (this.options.debug) { + console.log('方向计算:', { + x: axis0, + y: axis1, + angle: this.angle, + speed: this.speed + }); } } - - pressKey(buttons) { - this.buttons.forEach(button => { - const buttonData = buttons[button.index]; - button.pressed = buttonData ? buttonData.value === 1 : false; - - // 特别检查 Right Joystick Press 按钮 - if (button.name === "Right Joystick Press") { - this.rightJoystickPressed = button.pressed; - } - }); - } - + destroy() { - clearInterval(this.interval); - window.removeEventListener("gamepadconnected", this.onGamepadConnected); - window.removeEventListener("gamepaddisconnected", this.onGamepadDisconnected); - if (this.options.debug) { - console.log("GamepadController destroyed"); + if (this.updateLoop) { + clearInterval(this.updateLoop); } } } - -// 导出类以便外部使用 + export default GamepadController; \ No newline at end of file diff --git a/src/views/CarControl.vue b/src/views/CarControl.vue index 0053e9d..05e2c46 100644 --- a/src/views/CarControl.vue +++ b/src/views/CarControl.vue @@ -5,7 +5,8 @@
- 遥控车当前状态 + + {{ getDirectionText }} voice
@@ -23,19 +24,19 @@
屏幕 - +
警灯 - +
跟随 - +
避障 - +
@@ -114,13 +115,14 @@ export default { isRecording: false, audioHandler: null, reconnectTimer: null, // 添加重连定时器引用 - isComponentUnmounted: false // 添加组件卸载标志 + isComponentUnmounted: false, // 添加组件卸载标志 + isInitialized: false, // 添加初始化标志 } }, created() { - // 初始化 GamepadController,启用调试模式 + // 初始化 GamepadController,禁用调试模式 this.gamepadController = new GamepadController({ - debug: true, + debug: false, // 将 debug 设置为 false deadZone: 0.1, updateInterval: 50 }); @@ -150,7 +152,7 @@ export default { }, beforeDestroy() { this.isComponentUnmounted = true; // 标记组件已卸载 - + // 清除重连定时器 if (this.reconnectTimer) { clearTimeout(this.reconnectTimer); @@ -223,8 +225,8 @@ export default { initWebSocket() { try { console.log('正在连接 WebSocket...'); - // this.ws = new WebSocket('ws://192.168.4.120/ws'); - this.ws = new WebSocket('ws://192.168.1.120/ws'); + this.ws = new WebSocket('ws://192.168.4.120/ws'); + // this.ws = new WebSocket('ws://192.168.1.120/ws'); // this.ws = new WebSocket('ws://192.168.1.60:81'); @@ -277,13 +279,27 @@ export default { } }, - // 更新手柄数据 + // 修改 updateGamepadData 方法 updateGamepadData() { if (this.gamepadController) { // 获取手柄数据 const angle = this.gamepadController.angle; const directionAxis9 = this.gamepadController.directionAxis9; - const speed = this.gamepadController.speed; // 获取速度值 + const speed = this.gamepadController.speed; + + // 根据角度计算方向值(0-4) + let direction = 0; // 默认停止 + if (speed > 10) { // 添加速度阈值,避免小幅度移动 + if (angle >= 315 || angle < 45) { + direction = 4; // 右转 + } else if (angle >= 45 && angle < 135) { + direction = 2; // 后退 + } else if (angle >= 135 && angle < 225) { + direction = 3; // 左转 + } else if (angle >= 225 && angle < 315) { + direction = 1; // 前进 + } + } // 更新控制按钮状态 const wasPressed = this.isControlPressed; @@ -304,10 +320,10 @@ export default { } } - // 更新其他数据 - this.lastDirection = angle; - this.platform_fun = directionAxis9; - this.lastSpeed = speed; // 更新速度值 + // 更新手柄相关状态 + this.lastDirection = direction; + if (directionAxis9 !== undefined) this.platform_fun = directionAxis9; + if (speed !== undefined) this.lastSpeed = speed; } }, sendCarInfo() { @@ -333,26 +349,28 @@ export default { this.sendCarInfo(); }, + // 修改状态更新函数 updateCarStatus(data) { if (data.attribute) { - // 注释掉电池状态更新 - // this.batteryLevel = data.attribute.bat_quantity; // 更新障碍物显示状态 this.obstacleStatus = { - top: data.attribute.obstacle_sta === 0, - bottom: data.attribute.obstacle_sta === 1 + top: data.attribute.obstacle_sta === 1, + bottom: data.attribute.obstacle_sta === 2 }; + + // 只在初始化时更新开关状态 + if (!this.isInitialized) { + this.screenStatus = data.attribute.screen_en === 1; + this.warningLightStatus = data.attribute.warn_light_en === 1; + this.followStatus = data.attribute.follow_en === 1; + this.obstacleAvoidEnabled = data.attribute.obstacle_avoid_en === 1; + this.isInitialized = true; + } + } - // 更新开关状态 - this.platform_fun = data.attribute.platform; - this.screenStatus = data.attribute.screen_en === 1; - this.warningLightStatus = data.attribute.warn_light_en === 1; - this.followStatus = data.attribute.follow_en === 1; - this.obstacleAvoidEnabled = data.attribute.obstacle_avoid_en === 1; - - // 更新车辆状态 - this.lastSpeed = data.attribute.car_speed; - this.lastDirection = data.attribute.car_direction; + // 更新方向状态 + if (data.driver && typeof data.driver.direction !== 'undefined') { + this.lastDirection = data.driver.direction; // 使用返回的方向值 } }, @@ -364,9 +382,33 @@ export default { } }, + // 修改开关状态处理函数 + handleScreenChange(value) { + this.screenStatus = value; + this.sendControlData(); + }, + + handleWarningLightChange(value) { + this.warningLightStatus = value; + this.sendControlData(); + }, + + handleFollowChange(value) { + this.followStatus = value; + this.sendControlData(); + }, + + handleObstacleAvoidChange(value) { + this.obstacleAvoidEnabled = value; + this.sendControlData(); + }, + + // 修改 sendControlData 方法 sendControlData() { - // 先更新手柄数据 - this.updateGamepadData(); + // 只在有手柄数据时更新手柄相关状态 + if (this.gamepadController && this.gamepadController.isActive) { + this.updateGamepadData(); + } const controlData = { "JSON_id": 1, @@ -405,6 +447,23 @@ export default { return this.wsConnected ? require('../assets/img/connect.png') : require('../assets/img/no_connect.png'); + }, + getDirectionText() { + // 根据 direction 值显示对应状态 + switch (this.lastDirection) { + case 0: + return '遥控车已停止'; + case 1: + return '遥控车正在前进'; + case 2: + return '遥控车正在后退'; + case 3: + return '遥控车正在左转'; + case 4: + return '遥控车正在右转'; + default: + return '遥控车当前状态'; + } } }, setup() { @@ -464,6 +523,10 @@ export default { border: 2px solid #00ffff; padding: 2px; border-radius: 8px; + display: flex; + align-items: center; + justify-content: center; + min-width: 180px; /* 确保文本变化时盒子大小稳定 */ } .main-content { diff --git a/src/views/ConeControl.vue b/src/views/ConeControl.vue index 62c48c7..0c83bd8 100644 --- a/src/views/ConeControl.vue +++ b/src/views/ConeControl.vue @@ -67,6 +67,7 @@ 状态与控制
+