修复agent驱动程序、修复手柄路径保存逻辑、增加电机转速补偿

This commit is contained in:
张梦南 2026-04-20 16:12:10 +08:00
parent f48facde94
commit 7896e90602
7 changed files with 224 additions and 40 deletions

View File

@ -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 = `<p>正在${actionText}...</p>`;
}
// 记录操作(如果正在录制
// 记录操作(如果正在录制且动作发生变化
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');
}

View File

@ -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 = `<p>录制完成,共记录 ${recordedActions.length} 个操作</p>`;
console.log('Recording stopped, actions:', recordedActions);
window.isRecording = false;
status.innerHTML = `<p>录制完成,共记录 ${window.recordedActions.length} 个操作</p>`;
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 = '<p>开始录制...</p>';
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 = '<p>开始回放...</p>';
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 = '<p>回放完成</p>';
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 {

View File

@ -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 = `<p>开始录制...</p>`;
console.log('Recording started');

25
main/Path/test1.json Normal file
View File

@ -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
}
]
}

View File

@ -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
}
]
}

View File

@ -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": "无效的动作"}

View File

@ -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: