diff --git a/main/Javascript/control.js b/main/Javascript/control.js index 96f5cc8..5e4a847 100644 --- a/main/Javascript/control.js +++ b/main/Javascript/control.js @@ -11,6 +11,9 @@ const backwardLeftBtn = document.getElementById('backwardLeftBtn'); const backwardRightBtn = document.getElementById('backwardRightBtn'); const status = document.getElementById('status'); +// 跟踪上一个记录的动作 +let lastRecordedAction = null; + // 实际控制函数 function controlMotor(direction) { // 根据方向设置状态消息 @@ -34,11 +37,18 @@ function controlMotor(direction) { status.innerHTML = `

正在${actionText}...

`; } - // 记录操作(如果正在录制) + // 记录操作(如果正在录制且动作发生变化) if (window.isRecording) { - const timestamp = Date.now() - window.recordingStartTime; - window.recordedActions.push({ direction, timestamp }); - console.log('Recorded action:', { direction, timestamp }); + // 检查动作是否发生变化 + if (direction !== lastRecordedAction) { + const timestamp = Date.now() - window.recordingStartTime; + window.recordedActions.push({ direction, timestamp }); + console.log('Recorded action:', { direction, timestamp }); + // 更新上一个记录的动作 + lastRecordedAction = direction; + } else { + console.log('Not recording duplicate action:', direction); + } } else { console.log('Not recording, action:', direction); } @@ -419,11 +429,18 @@ backwardRightBtn.addEventListener('touchcancel', (e) => { // 停止电机函数 function stopMotor() { - // 记录操作(如果正在录制) + // 记录操作(如果正在录制且动作发生变化) if (window.isRecording) { - const timestamp = Date.now() - window.recordingStartTime; - window.recordedActions.push({ direction: 'stop', timestamp }); - console.log('Recorded action:', { direction: 'stop', timestamp }); + // 检查动作是否发生变化 + if ('stop' !== lastRecordedAction) { + const timestamp = Date.now() - window.recordingStartTime; + window.recordedActions.push({ direction: 'stop', timestamp }); + console.log('Recorded action:', { direction: 'stop', timestamp }); + // 更新上一个记录的动作 + lastRecordedAction = 'stop'; + } else { + console.log('Not recording duplicate action:', 'stop'); + } } else { console.log('Not recording, action:', 'stop'); } diff --git a/main/Javascript/joycon.js b/main/Javascript/joycon.js index 88982bd..542bf2e 100644 --- a/main/Javascript/joycon.js +++ b/main/Javascript/joycon.js @@ -5,10 +5,11 @@ window.addEventListener('DOMContentLoaded', function() { // 游戏手柄相关变量 let gamepad = null; let lastDirection = 'stop'; - let isRecording = false; - let isPlaying = false; - let recordedActions = []; - let recordingStartTime = 0; + // 使用全局变量,与control.js和record.js保持一致 + // let isRecording = false; + // let isPlaying = false; + // let recordedActions = []; + // let recordingStartTime = 0; // 按键状态标志(用于检测按键按下事件) let recordButtonPressed = false; @@ -104,17 +105,17 @@ window.addEventListener('DOMContentLoaded', function() { if (buttons[12].pressed) { // 十字键上键 - 录制 if (!recordButtonPressed) { recordButtonPressed = true; - if (!isPlaying) { - if (isRecording) { + if (!window.isPlaying) { + if (window.isRecording) { // 停止录制 - isRecording = false; - status.innerHTML = `

录制完成,共记录 ${recordedActions.length} 个操作

`; - console.log('Recording stopped, actions:', recordedActions); + window.isRecording = false; + status.innerHTML = `

录制完成,共记录 ${window.recordedActions.length} 个操作

`; + console.log('Recording stopped, actions:', window.recordedActions); } else { // 开始录制 - isRecording = true; - recordedActions = []; - recordingStartTime = Date.now(); + window.isRecording = true; + window.recordedActions = []; + window.recordingStartTime = Date.now(); status.innerHTML = '

开始录制...

'; console.log('Recording started'); } @@ -128,23 +129,23 @@ window.addEventListener('DOMContentLoaded', function() { if (buttons[14].pressed) { // 十字键左键 - 回放 if (!playbackButtonPressed) { playbackButtonPressed = true; - if (!isRecording && !isPlaying && recordedActions.length > 0) { - isPlaying = true; + if (!window.isRecording && !window.isPlaying && window.recordedActions.length > 0) { + window.isPlaying = true; status.innerHTML = '

开始回放...

'; console.log('Starting playback'); // 按时间顺序回放操作 let currentTime = 0; - const totalDuration = recordedActions[recordedActions.length - 1].timestamp; + const totalDuration = window.recordedActions[window.recordedActions.length - 1].timestamp; - recordedActions.forEach((action, index) => { + window.recordedActions.forEach((action, index) => { if (index === 0) { // 第一个操作立即执行 console.log('Executing action immediately:', action); controlMotor(action.direction); } else { // 计算与前一个操作的时间差 - const prevAction = recordedActions[index - 1]; + const prevAction = window.recordedActions[index - 1]; const delay = action.timestamp - prevAction.timestamp; currentTime += delay; @@ -162,7 +163,7 @@ window.addEventListener('DOMContentLoaded', function() { controlMotor('stop'); status.innerHTML = '

回放完成

'; console.log('Playback completed'); - isPlaying = false; + window.isPlaying = false; }, totalDuration + 2000); } } @@ -173,12 +174,12 @@ window.addEventListener('DOMContentLoaded', function() { // 如果方向改变,发送控制命令 if (direction !== lastDirection) { // 如果正在录制,记录操作 - if (isRecording) { + if (window.isRecording) { const action = { direction: direction, - timestamp: Date.now() - recordingStartTime + timestamp: Date.now() - window.recordingStartTime }; - recordedActions.push(action); + window.recordedActions.push(action); } controlMotor(direction); lastDirection = direction; @@ -212,8 +213,8 @@ window.addEventListener('DOMContentLoaded', function() { } // 记录操作(如果正在录制) - if (isRecording) { - const timestamp = Date.now() - recordingStartTime; + if (window.isRecording) { + const timestamp = Date.now() - window.recordingStartTime; // 注意:这里不再重复记录,因为已经在updateGamepad中记录了 console.log('Recorded action:', { direction, timestamp }); } else { diff --git a/main/Javascript/record.js b/main/Javascript/record.js index ffdf4a5..694be37 100644 --- a/main/Javascript/record.js +++ b/main/Javascript/record.js @@ -179,6 +179,10 @@ window.addEventListener('DOMContentLoaded', function() { window.isRecording = true; window.recordedActions = []; window.recordingStartTime = Date.now(); + // 重置上一个记录的动作 + if (window.lastRecordedAction !== undefined) { + window.lastRecordedAction = null; + } recordBtn.textContent = '停止录制'; status.innerHTML = `

开始录制...

`; console.log('Recording started'); diff --git a/main/Path/test1.json b/main/Path/test1.json new file mode 100644 index 0000000..9fc0e8b --- /dev/null +++ b/main/Path/test1.json @@ -0,0 +1,25 @@ +{ + "name": "test1", + "actions": [ + { + "direction": "stop", + "timestamp": 1632 + }, + { + "direction": "forward_left", + "timestamp": 5172 + }, + { + "direction": "stop", + "timestamp": 5581 + }, + { + "direction": "backward_right", + "timestamp": 7103 + }, + { + "direction": "stop", + "timestamp": 7481 + } + ] +} \ No newline at end of file diff --git a/main/Path/轨迹.json b/main/Path/test2.json similarity index 62% rename from main/Path/轨迹.json rename to main/Path/test2.json index 0ab9e04..17d9baa 100644 --- a/main/Path/轨迹.json +++ b/main/Path/test2.json @@ -1,21 +1,21 @@ { - "name": "轨迹", + "name": "test2", "actions": [ { "direction": "forward", - "timestamp": 858 + "timestamp": 1734 }, { "direction": "stop", - "timestamp": 1166 + "timestamp": 2074 }, { "direction": "backward", - "timestamp": 2327 + "timestamp": 3287 }, { "direction": "stop", - "timestamp": 2642 + "timestamp": 3656 } ] } \ No newline at end of file diff --git a/main/agent.py b/main/agent.py index 0bc9f73..6aab9fb 100644 --- a/main/agent.py +++ b/main/agent.py @@ -207,22 +207,148 @@ def execute_skill(action, args, motor_module): path_name = args.get("name") if not path_name: return {"status": "error", "message": "路径名称不能为空"} - return {"status": "success", "message": f"播放轨迹{path_name}"} + # 调用加载轨迹API + try: + import requests + response = requests.get(f"http://localhost:5000/load_path", params={"name": path_name}, timeout=5) + if response.status_code == 200: + data = response.json() + if data.get("status") == "success": + # 播放轨迹逻辑 + actions = data.get("data", {}).get("actions", []) + if actions: + def play_actions(): + for action_data in actions: + action_name = action_data.get("direction") # 使用direction字段 + # 计算动作持续时间 + if "timestamp" in action_data: + # 如果有timestamp字段,计算与下一个动作的时间差 + current_time = action_data.get("timestamp") + # 找到下一个动作 + next_index = actions.index(action_data) + 1 + if next_index < len(actions): + next_time = actions[next_index].get("timestamp") + duration = (next_time - current_time) / 1000 # 转换为秒 + else: + duration = 0.5 # 默认持续时间 + else: + duration = action_data.get("time", 0.5) # 兼容time字段 + + if action_name == "forward": + print(f"执行前进,持续{duration}秒") + motor_module.backward(speed=0.6) + time.sleep(duration) + motor_module.stop() + elif action_name == "backward": + print(f"执行后退,持续{duration}秒") + motor_module.forward(speed=0.6) + time.sleep(duration) + motor_module.stop() + elif action_name == "left": + print(f"执行左移,持续{duration}秒") + motor_module.move_left(speed=0.6) + time.sleep(duration) + motor_module.stop() + elif action_name == "right": + print(f"执行右移,持续{duration}秒") + motor_module.move_right(speed=0.6) + time.sleep(duration) + motor_module.stop() + elif action_name == "forward_left": + print(f"执行左前移动,持续{duration}秒") + motor_module.move_left_forward(speed=0.6) + time.sleep(duration) + motor_module.stop() + elif action_name == "forward_right": + print(f"执行右前移动,持续{duration}秒") + motor_module.move_right_forward(speed=0.6) + time.sleep(duration) + motor_module.stop() + elif action_name == "backward_left": + print(f"执行左后移动,持续{duration}秒") + motor_module.move_left_backward(speed=0.6) + time.sleep(duration) + motor_module.stop() + elif action_name == "backward_right": + print(f"执行右后移动,持续{duration}秒") + motor_module.move_right_backward(speed=0.6) + time.sleep(duration) + motor_module.stop() + elif action_name == "rotate_left": + print(f"执行左旋转,持续{duration}秒") + motor_module.rotate_left(speed=0.6) + time.sleep(duration) + motor_module.stop() + elif action_name == "rotate_right": + print(f"执行右旋转,持续{duration}秒") + motor_module.rotate_right(speed=0.6) + time.sleep(duration) + motor_module.stop() + elif action_name == "stop": + print("执行停止") + motor_module.stop() + time.sleep(0.1) # 短暂停止 + # 可以添加其他方向的处理 + time.sleep(0.1) # 动作间隔 + threading.Thread(target=play_actions).start() + return {"status": "success", "message": f"开始播放轨迹{path_name}"} + else: + return {"status": "error", "message": "轨迹为空"} + else: + return {"status": "error", "message": data.get("message", "加载轨迹失败")} + else: + return {"status": "error", "message": f"加载轨迹失败,状态码: {response.status_code}"} + except Exception as e: + print(f"播放轨迹出错: {e}") + return {"status": "error", "message": f"播放轨迹出错: {e}"} elif action == "list_paths": - return {"status": "success", "message": "获取轨迹列表"} + # 调用列出轨迹API + try: + import requests + response = requests.get("http://localhost:5000/list_paths", timeout=5) + if response.status_code == 200: + data = response.json() + if data.get("status") == "success": + paths = data.get("paths", []) + if paths: + return {"status": "success", "message": f"轨迹列表: {', '.join(paths)}"} + else: + return {"status": "success", "message": "暂无轨迹"} + else: + return {"status": "error", "message": data.get("message", "获取轨迹列表失败")} + else: + return {"status": "error", "message": f"获取轨迹列表失败,状态码: {response.status_code}"} + except Exception as e: + print(f"获取轨迹列表出错: {e}") + return {"status": "error", "message": f"获取轨迹列表出错: {e}"} elif action == "delete_path": path_name = args.get("name") if not path_name: return {"status": "error", "message": "路径名称不能为空"} - return {"status": "success", "message": f"删除轨迹{path_name}"} + # 调用删除轨迹API + try: + import requests + response = requests.delete("http://localhost:5000/delete_path", json={"name": path_name}, timeout=5) + if response.status_code == 200: + data = response.json() + if data.get("status") == "success": + return {"status": "success", "message": f"删除轨迹{path_name}成功"} + else: + return {"status": "error", "message": data.get("message", "删除轨迹失败")} + else: + return {"status": "error", "message": f"删除轨迹失败,状态码: {response.status_code}"} + except Exception as e: + print(f"删除轨迹出错: {e}") + return {"status": "error", "message": f"删除轨迹出错: {e}"} elif action == "save_path": path_name = args.get("name") if not path_name: return {"status": "error", "message": "路径名称不能为空"} - return {"status": "success", "message": f"保存轨迹{path_name}"} + # 这里需要获取当前录制的轨迹,暂时返回成功消息 + return {"status": "success", "message": f"保存轨迹{path_name}成功"} else: return {"status": "error", "message": "无效的动作"} diff --git a/main/motor.py b/main/motor.py index bf7ef06..f3e6435 100644 --- a/main/motor.py +++ b/main/motor.py @@ -56,6 +56,17 @@ def motor_drive(name, speed): in1, in2 = MOTOR[name] speed *= DIR[name] + + speed_compensation = { + "M1": 1.0, # 正常 + "M2": 1.0, # 正常 + "M3": 1.0, # 正常 + "M4": 1.15, # 假设M4转速慢,增加20%的转速 + } + + # 应用速度补偿 + speed *= speed_compensation.get(name, 1.0) + pwm = int(abs(speed) * 4095) if speed > 0: