JetBot 路径跟随项目:游戏手柄数据采集实现与解析

在 JetBot 路径跟随项目中,游戏手柄数据采集是实现遥控控制的关键环节。以下为完整的 Python 实现代码及解析:

import pygame
import csv
import time
import os

# 初始化pygame和手柄
pygame.init()
pygame.joystick.init()

# 创建数据存储目录
os.makedirs('joystick_data', exist_ok=True)

def collect_joystick_data():
    """采集游戏手柄数据并保存为CSV文件"""
    try:
        # 检测可用手柄
        if pygame.joystick.get_count() == 0:
            print("未检测到手柄设备")
            return
        
        joystick = pygame.joystick.Joystick(0)
        joystick.init()
        print(f"已连接手柄: {joystick.get_name()}")
        
        # 创建数据文件
        timestamp = time.strftime("%Y%m%d_%H%M%S")
        filename = f"joystick_data/joystick_{timestamp}.csv"
        
        with open(filename, 'w', newline='') as csvfile:
            fieldnames = ['timestamp', 'axis0', 'axis1', 'button0', 'button1']
            writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
            writer.writeheader()
            
            print("开始采集数据 (按SELECT按钮停止)...")
            running = True
            
            while running:
                for event in pygame.event.get():
                    if event.type == pygame.JOYBUTTONDOWN:
                        # SELECT按钮停止采集
                        if event.button == 6:  
                            running = False
                
                # 获取当前时间戳
                current_time = time.time()
                
                # 读取摇杆和按钮数据
                axis0 = joystick.get_axis(0)  # 左摇杆X轴
                axis1 = joystick.get_axis(1)  # 左摇杆Y轴
                button0 = joystick.get_button(0)  # A按钮
                button1 = joystick.get_button(1)  # B按钮
                
                # 写入CSV文件
                writer.writerow({
                    'timestamp': current_time,
                    'axis0': axis0,
                    'axis1': axis1,
                    'button0': button0,
                    'button1': button1
                })
                
                time.sleep(0.05)  # 50ms采样间隔
        
        print(f"数据已保存至: {filename}")
    
    except Exception as e:
        print(f"数据采集错误: {str(e)}")
    finally:
        pygame.quit()

if __name__ == "__main__":
    collect_joystick_data()

代码解析
1. 初始化模块
import pygame  # 手柄交互核心库
import csv     # 数据存储
import time    # 时间戳生成
import os      # 文件管理

  • Pygame 提供跨平台手柄支持
  • CSV模块 实现轻量级数据存储
  • 时间戳确保数据时序性
2. 数据采集流程
  1. 设备检测pygame.joystick.get_count() 验证手柄连接
  2. 文件创建:按时间戳生成唯一文件名
  3. 数据循环采集
    • 摇杆值范围:$[-1.0, 1.0]$
    • 按钮状态:$0$(释放)/$1$(按下)
  4. 终止条件:SELECT按钮(编号6)触发退出
3. 关键参数说明
参数 物理意义 数学表示
axis0 左摇杆X轴 $x \in [-1,1]$
axis1 左摇杆Y轴 $y \in [-1,1]$
button0 A按钮(确认) ${0,1}$
button1 B按钮(返回) ${0,1}$
采样间隔 20Hz (50ms) $\Delta t$
4. 数据结构示例
timestamp,axis0,axis1,button0,button1
1625000000.123,0.12,-0.85,0,1
1625000000.173,0.15,-0.82,0,1
1625000000.223,0.18,-0.78,1,0

数学建模

手柄输入与机器人运动的映射关系可表示为: $$ \begin{bmatrix} v \ \omega \end{bmatrix}

\begin{bmatrix} k_{vx} & 0 \ 0 & k_{\omega y} \end{bmatrix} \begin{bmatrix} x_{joystick} \ y_{joystick} \end{bmatrix} $$ 其中:

  • $v$ 为线速度
  • $\omega$ 为角速度
  • $k_{vx}$, $k_{\omega y}$ 为比例系数
  • $x_{joystick}$, $y_{joystick}$ 对应采集的 axis0, axis1
实际应用建议
  1. 数据增强:添加噪声 $\epsilon \sim \mathcal{N}(0,\sigma^2)$ 模拟操作波动
  2. 时间对齐:与摄像头数据通过时间戳同步
  3. 死区处理:对小摇杆值滤波
    deadzone = 0.1
    axis0 = 0 if abs(axis0) < deadzone else axis0
    

此实现为路径跟随项目提供基础控制数据,后续可结合视觉数据训练端到端控制模型。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐