20. 寻宝游戏
在本课中,你将把 PiCar-X 打造成一台**寻宝机器人**。 在房间里搭一个迷宫,并把六种不同颜色的卡片放在不同角落。 当找到目标颜色时,你的 PiCar-X会**搜索、识别并庆祝**。
这个项目结合了你目前学到的三项技能:
计算机视觉 —— 使用 Pi 摄像头检测彩色卡片。
键盘控制 —— 手动驾驶机器人穿越迷宫。
语音反馈 —— 由 Pico2Wave 播报目标颜色与成功提示。
这是一个有趣的游戏,展示了机器人如何像寻宝者一样**看、想、做**!
开始之前
确保你已经准备好以下内容:
安装所有模块(重要) — 安装
robot-hat、vilib、picar-x模块,然后运行脚本i2samp.sh。你可以下载并打印用于稳定颜色识别的:download:PDF 彩色卡片 <https://github.com/sunfounder/sf-pdf/raw/master/prop_card/object_detection/color-cards.pdf>。
运行代码
cd ~/picar-x/example
sudo python3 20.treasure_hunt.py
运行后,你会看到类似如下的信息:
* Running on http://0.0.0.0:9000/ (Press CTRL+C to quit)
然后在浏览器中打开``http://<your IP>:9000/mjpg``以查看实时视频流。
示例:http://192.168.18.113:9000/mjpg
游戏规则
机器人随机选择一个**目标颜色**并播报:“Look for red!”
你用键盘驾驶 PiCar-X:
w= 前进a= 左转s= 后退d= 右转space= 重复目标Ctrl+C= 退出
当摄像头看到目标彩色卡片时,PiCar-X会说**“Well done!”**
会选择一个新的目标颜色,继续寻宝!
代码
#!/usr/bin/env python3
from picarx import Picarx
from vilib import Vilib
from picarx.tts import Pico2Wave
from time import sleep
import threading
import readchar
import random
# -----------------------
# Settings
# -----------------------
COLORS = ["red", "orange", "yellow", "green", "blue", "purple"]
DETECTION_WIDTH_THRESHOLD = 100 # how wide the color blob must be
DRIVE_SPEED = 80
TURN_ANGLE = 30
MANUAL = """
Press keys to control PiCar-X:
w: forward a: turn left s: backward d: turn right
space: repeat target Ctrl+C: quit
"""
# -----------------------
# Init
# -----------------------
px = Picarx()
tts = Pico2Wave()
tts.set_lang("en-US")
current_color = "red"
key = None
lock = threading.Lock()
def say(line: str):
print(f"[SAY] {line}")
tts.say(line)
def renew_color_detect():
"""Choose a new target color and start detection."""
global current_color
current_color = random.choice(COLORS)
Vilib.color_detect(current_color)
say(f"Look for {current_color}!")
def key_scan_thread():
"""Background thread reading keys."""
global key
while True:
k = readchar.readkey()
# Map special keys before lowercasing
if k == readchar.key.SPACE:
mapped = "space"
elif k == readchar.key.CTRL_C:
mapped = "quit"
else:
mapped = k.lower()
with lock:
key = mapped
if mapped == "quit":
return
sleep(0.01)
def car_move(k: str):
if k == "w":
px.set_dir_servo_angle(0)
px.forward(DRIVE_SPEED)
elif k == "s":
px.set_dir_servo_angle(0)
px.backward(DRIVE_SPEED)
elif k == "a":
px.set_dir_servo_angle(-TURN_ANGLE)
px.forward(DRIVE_SPEED)
elif k == "d":
px.set_dir_servo_angle(TURN_ANGLE)
px.forward(DRIVE_SPEED)
def main():
global key
# Start camera and web preview
Vilib.camera_start(vflip=False, hflip=False)
Vilib.display(local=False, web=True)
sleep(0.8)
print(MANUAL.strip())
say("Game start!")
sleep(0.1)
renew_color_detect()
# Start keyboard thread (modern style)
key_thread = threading.Thread(target=key_scan_thread, daemon=True)
key_thread.start()
try:
while True:
# Check detection: if target color present and wide enough
if (Vilib.detect_obj_parameter.get("color_n", 0) != 0 and
Vilib.detect_obj_parameter.get("color_w", 0) > DETECTION_WIDTH_THRESHOLD):
say("Well done!")
sleep(0.1)
renew_color_detect()
# Take a snapshot of the last key (and clear it)
with lock:
k = key
key = None
# Handle movement / actions
if k in ("w", "a", "s", "d"):
car_move(k)
sleep(0.5)
px.stop()
elif k == "space":
say(f"Look for {current_color}!")
elif k == "quit":
print("\n[INFO] Quit requested.")
break
sleep(0.05)
except KeyboardInterrupt:
print("\n[INFO] Stopped by user.")
finally:
try:
Vilib.camera_close()
except Exception:
pass
px.stop()
say("Goodbye!")
sleep(0.2)
if __name__ == "__main__":
main()
工作原理
初始化
导入模块并配置 PiCar-X、摄像头和 TTS。
设置颜色列表、速度和转向角度。
目标选择
renew_color_detect()会随机选择一个目标颜色。机器人会通过 Pico2Wave 播报目标颜色。
键盘控制
key_scan_thread()在后台运行以捕获按键输入。w, a, s, d控制移动;space重复目标播报。
颜色检测
摄像头会持续检测目标颜色是否出现。
当检测到的色块足够大时,PiCar-X 会庆祝成功。
主循环
持续处理移动、检测与语音反馈。
退出时会优雅地停止机器人与摄像头。
故障排查
摄像头画面不工作?
运行
libcamera-hello检查树莓派摄像头是否正确连接。机器人无法识别颜色?
确保卡片打印清晰并放置在良好光照下。 试着调整
DETECTION_WIDTH_THRESHOLD的阈值。没有语音反馈?
检查是否安装了
pico2wave并确认音频输出设备设置正确。小车无法移动?
确认 PiCar-X 电源已打开,且电机校准无误。
通过完成本课程,你构建了一个 迷你寻宝游戏, 将 视觉、控制与交互 集成在同一个项目中!