touch_game:基于 ROS2 与 PrimeBot SDK 的人机触摸互动游戏项目

连拍两下机器人背部开局。它随机出题,你三秒内拍对部位;答对报反应时间,答错给答案,三轮结算并跟上局比。战绩存本地 JSON,跨局累计,全程不动机器人。

Branch1Tags0
FilesLast commitLast update
9 days ago
9 days ago
9 days ago
9 days ago
6 days ago
9 days ago
9 days ago
9 days ago

touch_game

拍两下机器人背部开局。它随机出题——"快,拍一下我的背!"配白色呼吸灯——你三秒内拍对地方算过,拍错了它告诉你正确答案,超时就催你手速。三轮打完报成绩,还会跟你上一局比。

做它的起因很简单:拿到 T1 之后发现触摸传感器有背部和胸部两组,能识别单击、双击和滑动,SDK 里正好是现成的事件流。那就干脆做个人机对战。

玩法

  1. 连拍两下背部 → 开局
  2. 机器人随机出题:语音口令 + 灯带提示(不同题配不同灯效,不看屏幕也知道该干嘛)
  3. 限时 3 秒做动作
  4. 答对报反应耗时,答错提示正确答案,超时挨催
  5. 结算播报战绩,跟上局纪录比,成绩写进 game_stats.json(留最近 5 局)

题目池

动作 event_type sensor_id
背部单击 1 1(背)
背部双击 2 1
胸部单击 1 2(胸)
胸部双击 2 2
背部上滑 9 1
背部下滑 8 1

跑起来

source ~/primebot_sdk/install/setup.bash
cd touch_game

python3 main.py --dry-run                  # 看玩法说明和题目池
python3 main.py --sim                      # 注入触摸序列打一局,不用真机
python3 main.py                            # 真机
python3 main.py --rounds 5 --time-limit 2  # 改轮数和限时

写的时候踩的坑

拿 timer 当 setTimeout 用了三次。 第一版冷却逻辑是 create_timer(2.0, cb),想着两秒后回到空闲态,结果 rclpy 的 timer 是周期性的,回调每两秒来一次,越积越多。后来干脆把状态机整个删掉——冷却本来就是一个时间戳比较,写成三个状态反而容易出错。删完五行代码,一次跑通。

--sim 里注册了定时器却没进 spin。 打了一句开场白就退出了,因为 timer 只在 spin 里执行,run() 返回后 main 就 shutdown 了。这个坑我在后面两个技能里又踩了一次,所以现在我给 sim 单独准备了一个 once 包装:回调第一行取消自己。

sim 的 mock 不干净,验证结果就不算数。 没有真机时服务调用会走超时重试,一次阻塞十秒,把冷却期的时间线全冲乱了——明明该丢弃的第二次点击被响应了。接口层加了 sim 开关,模拟模式下服务调用只打日志直接返回。

两处容易错的地方

触摸 topic 的官方规格是 Reliable / Depth=1 / 触发式上报,跟电池那套 Best Effort 正好相反,订阅端别乱设。

TTS 用的是交互优先级(INTERACTION_L6)并且 is_interrupted=True,不然连续出题会排队,最后一句命令等三秒才播。

目前的边界

  • 双击是传感器层给的 event_type=2,技能不自己判连击,所以拍得快慢得跟着固件来
  • 全程不动机器人:不切形态、不发速度,纯原地互动
  • 反应耗时从出题指令发出算起,把 TTS 播放时间也算进去了。要严格计时就等灯带亮起再动手

Introduction

连拍两下机器人背部开局。它随机出题,你三秒内拍对部位;答对报反应时间,答错给答案,三轮结算并跟上局比。战绩存本地 JSON,跨局累计,全程不动机器人。

Customize your domain