5. 线路追踪

本项目将使用灰度模块让 PiCar-X 沿着一条线向前移动。使用深色胶带制作一条尽可能直且 不太弯曲的线路。若 PiCar-X 偏离线路,可能需要进行一些实验调整。

运行代码

cd ~/picar-x/example
sudo python3 5.minecart_plus.py

运行代码后,PiCar-X 将沿着线路向前移动。

代码

备注

您可以 修改/重置/复制/运行/停止 以下代码。但在此之前,需进入源码路径,例如 picar-x/example。修改代码后,您可以直接运行以查看效果。

from picarx import Picarx
from time import sleep

px = Picarx()
# px = Picarx(grayscale_pins=['A0', 'A1', 'A2'])

# 请运行 ./calibration/grayscale_calibration.py 自动校准灰度值
# 或者通过以下代码手动修改参考值
# px.set_line_reference([1400, 1400, 1400])

current_state = None
px_power = 10
offset = 20
last_state = "stop"

def outHandle():
    global last_state, current_state
    if last_state == 'left':
        px.set_dir_servo_angle(-30)
        px.backward(10)
    elif last_state == 'right':
        px.set_dir_servo_angle(30)
        px.backward(10)
    while True:
        gm_val_list = px.get_grayscale_data()
        gm_state = get_status(gm_val_list)
        print("outHandle gm_val_list: %s, %s"%(gm_val_list, gm_state))
        currentSta = gm_state
        if currentSta != last_state:
            break
    sleep(0.001)

def get_status(val_list):
    _state = px.get_line_status(val_list)  # [bool, bool, bool], 0 表示线路,1 表示背景
    if _state == [0, 0, 0]:
        return 'stop'
    elif _state[1] == 1:
        return 'forward'
    elif _state[0] == 1:
        return 'right'
    elif _state[2] == 1:
        return 'left'

if __name__=='__main__':
    try:
        while True:
            gm_val_list = px.get_grayscale_data()
            gm_state = get_status(gm_val_list)
            print("gm_val_list: %s, %s"%(gm_val_list, gm_state))

            if gm_state != "stop":
                last_state = gm_state

            if gm_state == 'forward':
                px.set_dir_servo_angle(0)
                px.forward(px_power)
            elif gm_state == 'left':
                px.set_dir_servo_angle(offset)
                px.forward(px_power)
            elif gm_state == 'right':
                px.set_dir_servo_angle(-offset)
                px.forward(px_power)
            else:
                outHandle()
    finally:
        px.stop()
        print("stop and exit")
        sleep(0.1)

工作原理

该 Python 脚本使用灰度传感器控制 Picarx 机器人小车的导航。以下是其主要组成部分的说明:

  • 导入与初始化:

    脚本导入了控制机器人小车的 Picarx 类以及 time 模块中的 sleep 函数,用于添加延时操作。

    创建了 Picarx 的实例,注释行显示了一个使用特定灰度传感器引脚的初始化方法。

    from picarx import Picarx
    from time import sleep
    
    px = Picarx()
    
  • 配置与全局变量:

    current_statepx_poweroffsetlast_state 是用于跟踪和控制小车运动的全局变量。 px_power 设置电机功率, offset 用于调整转向角度。

    current_state = None
    px_power = 10
    offset = 20
    last_state = "stop"
    
  • outHandle 函数:

    当小车需要处理“脱线”情况时调用此函数。

    它根据 last_state 调整小车的方向,并检查灰度传感器值以确定新状态。

    def outHandle():
        global last_state, current_state
        if last_state == 'left':
            px.set_dir_servo_angle(-30)
            px.backward(10)
        elif last_state == 'right':
            px.set_dir_servo_angle(30)
            px.backward(10)
        while True:
            gm_val_list = px.get_grayscale_data()
            gm_state = get_status(gm_val_list)
            print("outHandle gm_val_list: %s, %s"%(gm_val_list, gm_state))
            currentSta = gm_state
            if currentSta != last_state:
                break
        sleep(0.001)
    
  • get_status 函数:

    此函数解释灰度传感器数据( val_list ),以确定小车的导航状态。

    根据哪个传感器检测到线路,小车的状态可以是“forward”(前进)、“left”(左转)、“right”(右转)或“stop”(停止)。

    def get_status(val_list):
        _state = px.get_line_status(val_list)  # [bool, bool, bool], 0 表示线路,1 表示背景
        if _state == [0, 0, 0]:
            return 'stop'
        elif _state[1] == 1:
            return 'forward'
        elif _state[0] == 1:
            return 'right'
        elif _state[2] == 1:
            return 'left'
    
  • 主循环:

    while True 循环不断检查灰度数据并相应调整小车的运动。

    根据 gm_state,它设置转向角度和运动方向。

    if __name__=='__main__':
        try:
            while True:
                gm_val_list = px.get_grayscale_data()
                gm_state = get_status(gm_val_list)
                print("gm_val_list: %s, %s"%(gm_val_list, gm_state))
    
                if gm_state != "stop":
                    last_state = gm_state
    
                if gm_state == 'forward':
                    px.set_dir_servo_angle(0)
                    px.forward(px_power)
                elif gm_state == 'left':
                    px.set_dir_servo_angle(offset)
                    px.forward(px_power)
                elif gm_state == 'right':
                    px.set_dir_servo_angle(-offset)
                    px.forward(px_power)
                else:
                    outHandle()
    
  • 安全与清理:

    try...finally 块确保脚本中断或结束时小车能够安全停止。

    finally:
    px.stop()
    print("stop and exit")
    sleep(0.1)
    

总结,该脚本利用灰度传感器引导 Picarx 机器人小车沿线路导航。它通过连续读取传感器数据来确定方向,并相应调整小车的运动和转向。 outHandle 函数为小车在需要大幅调整路径时提供额外逻辑支持。